Index: projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/base.css
===================================================================
--- projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/base.css	(revision 4)
+++ projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/base.css	(revision 4)
@@ -0,0 +1,230 @@
+@charset "UTF-8";
+
+HTML {
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	BACKGROUND: #FFF
+	PADDING-BOTTOM: 0px;
+	MARGIN: 0px;
+	PADDING-TOP: 0px;
+}
+
+BODY {
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	FONT-SIZE: small;
+	BACKGROUND: #FFF;
+	PADDING-BOTTOM: 0px;
+	MARGIN: 1px;
+	PADDING-TOP: 0px;
+	FONT-FAMILY: "Trebuchet MS", Verdana, "Lucida Sans", "Lucida Sans Unicode", Arial, Sans-Serif;
+}
+
+/*
+"",inherit
+}
+*/
+
+.clear {
+	CLEAR: both
+}
+.pad {
+	padding: 5px;
+
+}
+
+.menuBox {
+	padding: 5px;
+	border: 1px solid #DDD;
+	margin: 0px 10px 10px 10px;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	text-align: left;
+}
+
+.menuBox ul {
+  margin: 0px 0px 10px 5px;
+@padding: 10px 30px;
+	list-style-image: url('./images/li_bl.gif');
+}
+
+.menuBox h2 {
+	margin: 10px 0px 10px 0px;
+	padding: 3px 3px 3px 8px;
+	font-size: 100%;
+	color: #8F8F8F;
+	background: #FFF url(./images/gray_stripe.png);
+	background-repeat: repeat-x;
+	letter-spacing: 0pt;
+	border-left: 4px solid #CCC;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+
+P {
+	PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 0px
+}
+
+a {
+	color: #9c9c9c;
+	text-decoration: none;
+	font-weight: bold;
+}
+a:hover {
+	color: #E92;
+	text-decoration: underline;
+}
+
+a:visited {
+  color: #9c9c9c;
+}
+
+a:visited:hover {
+	color: #E92;
+	text-decoration: underline;
+}
+
+#header {
+	width: 100%;
+	height: 95px;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	margin: 0px;
+}
+
+#header img {
+	margin-left: -5px;
+	margin-top: 17px;
+}
+
+
+
+
+
+p,dl {
+	margin: 5px 10px 10px 20px;
+}
+dt {
+	margin-left: 10px;
+	font-weight: bold;
+	color: #888;
+}
+dd {
+	margin-bottom: 5px;
+}
+
+
+/* padding for IE indent problem. */
+
+
+
+
+
+#container {
+	PADDING-TOP: 0px;
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	PADDING-BOTTOM: 0px;
+	WIDTH: 100%;
+	background: #FFF;
+	margin-top: 5px;
+}
+
+#container img {
+	margin: 5px;
+	padding: 5px;
+	border: 1px solid #DDD;
+}
+
+
+
+#left-container {
+	background: #CCC url(./images/stripe.gif);
+	FLOAT: left;
+	WIDTH: 100%;
+	MARGIN-RIGHT: -200px;
+	padding-top: 10px;
+}
+
+#left-container .sub {
+	FLOAT: right;
+	MARGIN-LEFT: -200px;
+	WIDTH: 100%;
+}
+
+#right-container {
+	padding-top: 10px;
+}
+
+
+#main {
+	PADDING: 0px;
+	BACKGROUND: #EEE;
+	MARGIN: 0px 200px 150px 200px;
+	border: 1px solid #D2D2D2;
+}
+
+#main ul {
+  margin: 0px 0px 10px 10px;
+@padding: 10px 30px;
+  list-style-image: url('./images/li_bl.gif');
+}
+
+
+#main h2 {
+	margin: 5px 0px 10px 0px;
+	padding: 7px;
+	font-size: 110%;
+	color: #8F8F8F;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	letter-spacing: 1pt;
+	border-left: 6px solid #BBB;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+#main h3 {
+	margin: 5px 0px 5px 11px;
+	padding: 3px 3px 3px 6px;
+	font-size: 105%;
+	color: #8F8F8F;
+	letter-spacing: 1pt;
+	background: #FFF url(./images/bg_gray.png);
+	border-left: 5px solid #CCC;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+#main h4 {
+	margin: 5px 5px 5px 20px;
+	padding: 2px 2px 2px 10px;
+    letter-spacing: 1pt;
+	font-size: 100%;
+	color: #666;
+	border-bottom: 2px dotted #CCC;
+}
+
+
+#left {
+	CLEAR: all;
+
+	FLOAT: left;
+	WIDTH: 200px;
+}
+#right {
+
+	FLOAT: right;
+	WIDTH: 200px;
+}
+
+#footer {
+	BACKGROUND: #E5E5E5;
+	width: 100%;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	text-align: center;
+}
+
+
Index: projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/index.html
===================================================================
--- projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/index.html	(revision 4)
+++ projectionDesigner/tag/ProjectionDesigner_1.1.5/doc/index.html	(revision 4)
@@ -0,0 +1,318 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html lang="ja">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Projection Designer</title>
+	<meta http-equiv="content-style-type" content="text/css">
+	<meta http-equiv="content-language" content="en">
+	<link rel="stylesheet" href="base.css" type="text/css">
+    <style type="text/css">
+<!--
+.style2 {font-size: 36px}
+.style4 {font-size: 16px}
+-->
+    </style>
+</head>
+<body>
+
+<DIV id=header>
+  <p>
+    <!--<H1>Inneroptics CSS Layouts</H1>-->
+    </p>
+  <p><span class="style2">Projection Designer </span><span class="style4">ver.1.1.0<br>
+  Projection Environment Setup Tool</span></p>
+</DIV>
+
+<!-- ************* body ****************-->
+<DIV id=container>
+<DIV id=left-container>
+<DIV class=sub>
+
+<DIV id=main>
+<DIV class=pad>
+
+<a name="overview"><h2>Overview</h2></a>
+<p><strong>ProjectionDesigner</strong> is a setup tool for distortion correction and edge blending in  multiple projection theater environments with various types of screen shapes.  With this tool you can setup virtual projectors and a virtual screen in 3d  environment to simulate the projection. You should run this tool in the actual  environment to confirm the result of the simulation in real-time. After the  setup, this tool exports the setup result as a <strong>&lsquo;Projection data set&rsquo;</strong> &ndash; <strong>Distortion  map image</strong>, <strong>Blending map image</strong> and <strong>View matrix file</strong>. This data set  is basic information for projection in your environment.</p>
+<p>You can use a movie converter tool with  this data set to split and distort movie files for each projector. If you can  link GLRC(OpenGL rendering composite library) with your OpenGL application, the  application will load this data set for distortion correction and edge blending  in real-time. With a special OpenGL replacement driver GLWare, you can also  make these corrections for many OpenGL based applications without their source  code.</p>
+<p>This projection data set is simple,  universal and not depends on implementation of applications. So you can make  OpenGL or DirectX based 3d application, converter tools and etc based on this  data set. From content creator&rsquo;s point of view, you can expect that each theater  has its own projection data set made by its user or vendor. So you can focus  your energy on creating immersive content itself, not depending on actual theater  environments.</p>
+<p>ProjectionDesigner is a primitive, manual  based setup tool. Basically it has no auto calibration functions such as  (patented) camera-projector feedback algorithm. It&rsquo;s important that there is at  least one way to make the projection data set for free. If you want more  automated, easy way to achieve the result, you should look for other tools.</p>
+<a name="mainfeatures">
+<h2>Main features </h2>
+</a>
+<ul>
+  <li>Virtual screen and projectors simulation  in real-time 3d environment.</li>
+  <li>Server / client synchronization for  multiple PC projection environments.</li>
+  <li>Supports plane, box, dome and any  polygon-based shape screen.</li>
+  <li>Projector&rsquo;s position, direction, field of  view, aspect ratio lens shift is configurable.</li>
+  <li>2d-based direct distortion / blend map  shape manipulation.</li>
+  <li>Image overlaying on projection image for  reference.</li>
+  <li>Simple Wavefront (.obj) format model  importer for sample scene.</li>
+  <li>Open format. Open source. Freely  available!</li>
+</ul>
+
+
+
+<a name="screenshots">
+<h2>Screenshots</h2>
+</a>
+<p><a href="images/projdesigner.png" target="_blank"><img src="images/projdesigner_s.png" alt="ProjectionDesigner GUI" width="128" height="96" border="0"></a> <a href="images/onscreen.png" target="_blank"><img src="images/onscreen_s.png" alt="Projected image on screen" width="128" height="96" border="0"></a> <a href="images/distortwindow.png" target="_blank"><img src="images/distortwindow_s.png" alt="Distortion design" width="96" height="76" border="0"></a> <a href="images/blendwindow.png" target="_blank"><img src="images/blendwindow_s.png" alt="Blend map design" width="96" height="76" border="0"></a></p>
+
+
+
+<a name="author">
+<h2>Author</h2>
+</a>
+<p>Toshiyuki Takahei (takahei&lt;at&gt;orihalcon.jp)</p>
+
+
+
+<a name="platform"><h2>Platform</h2></a>
+<p>Windows 2000/XP</p>
+<a name="licence"><h2>Licence</h2></a>
+<p>General Public Licence (GPL) / Commercial License (Dual License) </p>
+
+
+
+<a name="download"><h2>Download</h2></a>
+<p><a href="http://www.orihalcon.jp/download/projdesigner_1.1.0.zip">Source and Windows binary</a></p>
+
+
+<a name="preparation"><h2>Preparation</h2></a>
+<h3>Hardware setup </h3>
+
+<p>When you setup the projection system with  ProjectionDesigner, you should run it in actual projectors and PCs. In the  following adjustment step, you&rsquo;ll put virtual projectors and a screen strictly  same as the actual ones, and project the simulated distortion images with the  actual hardware to check the precise of result for more detail adjustment. For  this reason, you need actual number of projectors to use, and one more screen  to display the ProjectionDesigner user interface. You can use graphic cards  with multiple display output, and networked PCs to prepare the enough number of  displays.</p>
+<p>ProjectionDesigner heavily uses OpenGL  functions, especially off-screen rendering features such as a P-Buffer. You  should use the latest graphic card and powerful PC you have. You should also  install the latest graphic card driver.</p>
+<p>To minimize the number of variable projector&rsquo;s  parameters, you should disable projector&rsquo;s own distortion correction. You  should also set the same parameters to zoom angle, lens shift, brightness and  so on for all projectors you use. </p>
+<h3>Network setup</h3>
+<p>If you want to use ProjectionDesigner as server /  client system over LAN environment, prepare your PC to be able to connect each  other, and open a socket port (default port number is 55555) in firewall. I  recommend to put ProjectionDesigner in a share folder where all PCs can access,  and use the same program file. In this case, if you need many connections more  than Window&rsquo;s limitation (ex. 8 in WindowsXP), you should put the files in  non-Windows based NAS.</p>
+<h3>Execute and Exit program</h3>
+<h4>Boot as Standalone / Server</h4>
+<p>When you use ProjectionDesigner only in one  PC, or use it on a server PC to do adjustment work, run <strong>projdesigner.exe</strong> program without arguments. If you want to specify a custom port  number, use <strong>[-portno]</strong> option.</p>
+<p><strong>projdesigner.exe [-portno 12345]</strong></p>
+<h4>Boot as Client</h4>
+<p>When you use ProjectionDesigner on a client  PC which connected to projectors, run <strong>projdesigner.exe</strong> program with <strong>[-client]</strong> option. You should give a server address with <strong>[-address]</strong> option, and a custom port number with <strong>[-portno]</strong> option.</p>
+<p><strong>projdesigner.exe &ndash;client &ndash;address 192.168.0.10 [-portno  12345]</strong></p>
+<p>If the client program can not connect a server  program, it tries to connect the server again and again. So you can boot a  server after clients. But when you change number of clients or their host name,  you should execute <strong>[File]</strong> &gt; <strong>[Sync Clients]</strong> in menu for synchronization. It  will be described in detail later. </p>
+<h4>Exit the program</h4>
+
+<p>You can quit standalone / server program by <strong>[File] &gt; [Exit]</strong> in menu or click <strong>[X]</strong> button on the title bar. If your client program is displayed  in full screen mode and menus are hidden, hit <strong>[Alt]  + [Return]</strong> to cancel the full screen mode. You can also quit  server and all client programs at once by <strong>[File]  &gt; [Exit All]</strong> in server&rsquo;s menu. When you close the standalone /  server program, all unsaved data will be discarded. Needless to say, save your  data before exit the program!</p>
+
+
+<a name="tutorial"><h3>Tutorial</h3></a>
+<p>In the following section describes each step of adjustment with ProjectionDesigner.</p>
+<h4>Execute programs</h4>
+<p>At first run <strong>projdesigner.exe</strong> on a server PC which has a screen to display the  ProjectionDesigner&rsquo;s adjustment user interface. Then run <strong>projdesigner.exe</strong> on client PCs with <strong>[-client]</strong> option and <strong>[-address]</strong> option with the server&rsquo;s address as a client mode. If  the clients successfully connect to the server, a message &ldquo;Connected to server:  server address&rdquo; is displayed in their log area.</p>
+<h4>Setup screen shape</h4>
+
+
+
+<p>Click <strong>[Screen]</strong> tab in GUI panel, select a shape type in <strong>[Shape]</strong> group&rsquo;s <strong>[Type]</strong> combo box. Set screen&rsquo;s size depends on its shape type (unit is meter). In some  screen shape, you can set wire frame resolution. If you can mark reference  points on screen surface, or if your screen has some geometrical hint for  reference, it&rsquo;s highly useful for later adjustment to set the wire frame  resolution to match the reference points. Set your screen&rsquo;s position, rotation  and scale in the <strong>[Screen]</strong> tab&rsquo;s <strong>[Transform]</strong> group. Check <strong>[Wire  frame]</strong> to display screen&rsquo;s wire frame grid.</p>
+<h4>Add a Channel</h4>
+<p>Let&rsquo;s add the first Channel. <strong>&lsquo;Channel&rsquo;</strong> means a set which consists of one projector (&lsquo;<strong>Projector&rsquo;</strong>) and rendering view (<strong>&lsquo;View&rsquo;</strong>) for it. This first channel becomes the basis of the following  other channel, so setup this channel accurately as much as you can.</p>
+<p>Click <strong>[Channels]</strong> tab in GUI panel, click <strong>[Add]</strong> button  to add a channel. In [Name] field you can set name of channel. Channel name must  be unique among all channels.</p>
+<h4>Setup for projection</h4>
+<p>If you&rsquo;re connecting the first channel&rsquo;s  projector to the server PC, click <strong>[Open Window&hellip;]</strong> button at the bottom of <strong>[Channels]</strong> tab. When a <strong>Projector Window</strong> appears, move  it to the screen for projection, click somewhere in the window, then hit <strong>[Alt]  + [Return]</strong> to toggle it to full screen mode.<img src="images/remotesettings.png" alt="Remote Settings" width="233" height="155" align="right"></p>
+<p>If you want to use a client PC for the  first channel, click <strong>[Remote Settings]</strong> in <strong>[Channels] </strong>tab, and set client  PC&rsquo;s network host name in <strong>[Host name]</strong> field. Then click <strong>[Full screen]</strong> check box to full screen mode. After that, select <strong>[File]  &gt; [Sync Clients]</strong> in menu to synchronize between  server and clients.</p>
+<p>Now you have ProjectionDesigner&rsquo;s main window and one  other screen for projection of the first channel. In the following steps, you  should adjust parameters by actually projecting the channel image on the  screen. </p>
+<h4>Setup Projector's parameters</h4>
+<p><img src="images/projectorsettings.png" alt="Projector Settings" width="234" height="304" align="right">Click <strong>[Channels]</strong> tab in GUI panel, then click <strong>[Projector]</strong> to open a sub panel. In this panel, set <strong>[FOV]</strong> (projector&rsquo;s vertical field of view in degree) and <strong>[Aspect]</strong> (projector&rsquo;s aspect ratio, width/height. Ex. 1.33333  in XGA) values refer to its spec sheet. If your projector projects image to  upper direction (most projectors do it), you should set <strong>[Off-axis X, Y]</strong> value (offset distance of image center at 1m from the  projector&rsquo;s center). Though these parameters are anytime adjustable in  real-time, but I recommend to set precise values at first, and use the same  value among all projectors.</p>
+<p>Next, let's setup position and direction of the  first channel&rsquo;s Projector. In the 3D area there is a screen and projector&rsquo;s  projection area. Purpose of this step is to make the projector&rsquo;s parameters to  the actual one. But in most case it is difficult to measure the projector&rsquo;s  precise position and direction, you should use wire frame grid to match it to  reference points or geometrical hints.</p>
+<p> You can set parameter values in fields of <strong>[Projector</strong>] sub panel in <strong>[Channels]</strong> tab, or use the following keyboard shortcuts in 3D area. To use keyboard  shortcuts, hit <strong>[Esc]</strong> key first to focus on 3D  area.</p>
+<p> I repeat that precise of first channel&rsquo;s  adjustment effects the following channels. Keep it in mind and setup precisely  as much as you can.</p>
+<p><strong>Shortcut keys in 3D area</strong></p>
+<p><table border="1">
+  <tr>
+    <th>Shortcut</th>
+    <th>Meanings</th>
+  </tr>
+  <tr>
+    <td><strong>Mouse  left drag</strong></td>
+    <td>Rotation  of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>Mouse  right drag </strong></td>
+    <td>Pan  of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>Mouse  wheel</strong></td>
+    <td>Change  distance of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>[Cursor  key]</strong></td>
+    <td>Change  direction of Projector / View.*</td>
+  </tr>
+  <tr>
+    <td><strong>[Home][End]</strong></td>
+    <td>Change direction  (roll) of Projector / View.*</td>
+  </tr>
+  <tr>
+    <td><strong>[8][4][6][2]</strong></td>
+    <td>Move Projector /  View horizontally.*</td>
+  </tr>
+  <tr>
+    <td><strong>[9][3]</strong></td>
+    <td>Move  Projector / View vertically.*</td>
+  </tr>
+  <tr>
+    <td><strong>[+][-][*][/]</strong></td>
+    <td>Change  Projector / View &lsquo;s lens shift value.*</td>
+  </tr>
+  <tr>
+    <td><strong>[.][,]</strong></td>
+    <td>Change  Projector / View &lsquo;s field of view.*</td>
+  </tr>
+  <tr>
+    <td><strong>[F1]-[F5]</strong></td>
+    <td>Change 3D view mode.</td>
+  </tr>
+  <tr>
+    <td><strong>[Q]</strong></td>
+    <td>Switch  operation mode between Projector and View.</td>
+  </tr>
+  <tr>
+    <td><strong>[T]</strong></td>
+    <td>Switch  move coordinate between Local and World.</td>
+  </tr>
+  <tr>
+    <td><strong>[Space]</strong></td>
+    <td>Change the current channel.</td>
+  </tr>
+  <tr>
+    <td><strong>[A]</strong></td>
+    <td>Show or hide coordinate axes.</td>
+  </tr>
+  <tr>
+    <td><strong>[G]</strong></td>
+    <td>Show or hide grid frame.</td>
+  </tr>
+  <tr>
+    <td><strong>[I]</strong></td>
+    <td>Show or hide information at upper left corner.</td>
+  </tr>
+  <tr>
+    <td><strong>[Esc]</strong></td>
+    <td>Focus on 3D area.</td>
+  </tr>
+</table>
+</p>
+<p>* marked shortcut  can adjust values in 1/10 accuracy with <strong>[Shift]</strong> key, in 1/100 accuracy with <strong>[Shift] +  [Ctrl]</strong> keys.</p>
+<h4>Setup View parameters</h4>
+<p><img src="images/viewsettings.png" alt="View Settings" width="234" height="247" align="right">After the Projector setup, you need to setup View  parameters. View means rendering area of the scene. In practice, you should adjust  it as a view from the sweet spot (a point where you can see undistorted image  in the theater), covering whole projector&rsquo;s projected area on the screen  surface. <strong>[Channels]</strong> tab in GUI panel has a channel list at the top of it.  In this channel list, click <strong>[P]</strong>(Projector) cell of the current channel twice to make  it gray check, click <strong>[V]</strong>(View) to make it gray check too. Now you can see blue  Projector area and yellow View area on the screen surface. Let&rsquo;s adjust the  yellow area to cover whole blue area. Hit <strong>[Esc]</strong> key to focus on 3D area, <strong>[Q]</strong> key to switch View operation mode. Move the View to  sweet spot where the best view position in the theater (ex. In dome screen, it  should center of the dome &ndash; origin of the coordinate). Then change direction of  the View by <strong>[Cursor key]</strong>,<strong>[Home]</strong>,<strong>[End]</strong> key, and change FOV by <strong>[.]</strong>,<strong>[,]</strong> key to cover the whole blue area. More the View area  becomes closer to Projector area, higher distortion rendering quality you&rsquo;ll get.</p>
+<h4>Save your projection setup data</h4>
+<p>Now you finished the first channel setup. You  should save the current setup data. Select [File] &gt; [Save As] in menu to  save the current data to xml file. Needless to say, you should save data  frequently.</p>
+<h4>Setup other channels</h4>
+<p>For the next step, you should setup the  next channel. In <strong>[Channels]</strong> tab in GUI panel, click <strong>[Add]</strong> button to add a new channel. Added new channel has the same parameter values as  the first channel (last selected channel) as default. It&rsquo;s useful when you  setup left channel after right channel.</p>
+<p>You can setup the new channel same as the  first channel. When you adjust the Projector of the new channel, you&rsquo;ll notify  that when the two projector&rsquo;s projection area are overlapped, edge of the  projection area is visible in another projector&rsquo;s projection image. It will be  helpful hint for precise adjustment. With these hints you may be able to setup  the following channels easier than the first one. But you should keep in mind  that adjustment errors are accumulated in each channel. You still need to work precisely.</p>
+<h4>Test with a sample scene</h4>
+<p><img src="images/channellist.png" alt="Channel List" width="234" height="190" align="right">Now let&rsquo;s see a sample scene with adjusted  distortion correction. In channel list in <strong>[Channels]</strong> tab of GUI panel, make all <strong>[P]</strong>(Projector) and <strong>[V]</strong>(View)  to be unchecked, and make all <strong>[S]</strong>(Scene)  to be checked by clicking header of the channel list. If you setup the  projection correctly, you can see an undistorted teapot model from the sweet  spot in your theater. If you need higher resolution for distortion correction,  select <strong>[Edit] &gt; [Preference&hellip;]</strong> in menu  to open <strong>Preference Dialog</strong>, and then  change <strong>[Size]</strong> value in <strong>[Off-screen  Scene Rendering]</strong> group.</p>
+<p>You can freely move the sample scene  object. Select <strong>[Window] &gt; [Scene Viewer&hellip;]</strong> in  menu to open <strong>Scene Viewer Window</strong>. In this  window, you can rotate the scene by mouse left drag, and change distance from  the object by mouse wheel.</p>
+<h4>Warp distortion for detail adjustment</h4>
+<p><img src="images/distortwindow_m.png" alt="Distortion map design" width="240" height="190" align="right">In spite of the careful setup, accumulation  of adjustment, screen shape and lens distortion error may cause small but  unfixable projection error. For these cases, you can use direct image  distortion to tweak the distortion correction. Keep in mind that this direct  tweak does not reflect geometrical information. You must use it for tiny error  only.</p>
+<p>Select <strong>[Channels]</strong> tab in GUI panel, and then check <strong>[Enable]</strong> check  box in <strong>[Warp]</strong> group. Click <strong>[Open Window&hellip;]</strong> button to open <strong>Projector  Window</strong> on the server PC. Since you activated the warp  flag, you&rsquo;ll see yellow control points in the <strong>Projector  Window</strong>. You can tweak the projection image directly by  dragging these yellow control points. If you want more control points, set <strong>[Res.]</strong> value  in <strong>[Warp]</strong> group. Notice that when you change the number of control points, the current  setup of control points will be discarded. You can reset the control points by  clicking <strong>[Reset]</strong> button. </p>
+<h4>Make a blend map</h4>
+<p><img src="images/blendwindow_m.png" alt="Blend map design" width="240" height="190" align="right">When you use multiple projectors, you&rsquo;ll  notice that projector&rsquo;s overlapped area will becomes brighter. To equalize  intensity on the screen surface, you need to make a <strong>blend map</strong> which represents darken overlapped area.</p>
+<p>To make a blend map in ProjectionDesigner,  select <strong>[Edit] &gt; [Blend Map]</strong> in menu  to switch to blend map editing mode. In the actual projection environment, you&rsquo;ll  see the white images of all projectors cause undesirable intensity  distribution. Select a channel to make a blend map in the channel list in <strong>[Channels]</strong> tab, click <strong>[Open Window&hellip;] </strong>button to open <strong>Projector Window</strong>. Click somewhere in the window and hit <strong>[Space]</strong> key to confirm switching selected blend channel name displayed at  the upper left corner. Now select a channel which overlapped on the current  channel by hitting <strong>[Space]</strong> key  some times. You can darken the blend channel by hitting <strong>[B]</strong> key. Adjust the blend value by <strong>[B]</strong>,<strong>[D]</strong> key until achieving flat  intensity distribution on the screen surface.</p>
+<p>You can smooth the blending edge for seamless  intensity distribution. Select <strong>[Edit]  &gt; [Preference&hellip;]</strong> in menu to open <strong>Preference Dialog</strong>, check <strong>[Soft  edge]</strong> in <strong>[Blend  Map]</strong> group. You can also change width and intensity  curve of the blending edge by editing <strong>[Width]</strong> and <strong>[Exponent]</strong> fields.</p>
+<h4>Export the Projection data set</h4>
+<p><img src="images/preferencedialog.png" alt="Preference Dialog" width="343" height="377" align="right">After finishing the projection setup,  export the Projection data set to use it in other applications. Save the  current data at first, then select <strong>[File] &gt; [Export Data set&hellip;]</strong> in menu to export the data set. The Projection data set will be  exported in the same directory as the data file saved like:</p>
+<p>distort_CHANNELNAME.png<br>
+blend_CHANNELNAME.png<br>
+view_CHANNELNAME.cfg</p>
+<p>You can change size of distortion map and  blend map image. Select <strong>[Edit] &gt; [Preference&hellip;]</strong> in menu to open <strong>Preference Dialog</strong>, and then change <strong>[Image size]</strong> value in <strong>[Export]</strong> group. You can also set file name pattern in the <strong>Preference  Dialog</strong>. In the file name pattern setting,  <strong>%CHANNELNAME%</strong> will be replaced to channel name, <strong>%CHANNELINDEX%</strong> to channel  index, <strong>%REMOTEHOST%</strong> to remote host name.</p>
+<p align="right">&nbsp;</p>
+<a name="formats"><h2>Format of Projection data set</h2></a>
+<p>This chapter explains format specifications of the  Projection data set.</p>
+<h3>Distortion map image</h3>
+<p><img src="images/distortmap.png" alt="Distortion map image" width="128" height="128" align="right">In distortion correction, you need to  pre-warp a rendered image to make a projection image on a screen surface  undistorted viewed from a sweet spot in your theater. Distortion map defines  where each pixel in the projection image mapped from undistorted rendered image.  Color value of each pixel in the distortion map image represents normalized  coordinate in the rendered image.</p>
+<p>&nbsp; X =  ( B / 255 + ( R mod 16 ) ) / 16.<br>
+  &nbsp; Y =  ( G / 255+ ( R  / 16 ) ) / 16.</p>
+<p>Here, X and Y is normalized coordinate (0.0-1.0) in  the rendered image, R, G and B is color element value in the distortion map  (0-255). You can use this formula in your shader code or texture mapping  coordinate generation code to realize the distortion correction.</p>
+<h3>Blend map image</h3>
+<p><img src="images/blendmap.png" alt="Blend map image" width="128" height="128" align="right">In multiple projector environments, you need to  darken overlapped area of projectors to flatten intensity on the screen  surface. Blend map represents intensity distribution and color correction for  the projection image. You should multiply this blend map image to projection  image which is pre-warped by the distortion map.</p>
+<h3>View matrix file</h3>
+<p>View matrix file defines View&rsquo;s model/view  matrix and projection matrix of a channel for rendering in your 3D application.</p>
+<p>This file is a simple text file nested by &lsquo;{&lsquo;  and &lsquo;}&rsquo; &nbsp;blocks. The most outer block is &quot;Channel&quot; like this: </p>
+<p>Camera &ldquo;CHANNELNAME&rdquo; { &hellip; }</p>
+<p>In this block, the following &quot;Lens&quot; block represents  a projection matrix of the View.</p>
+<p>&nbsp;&nbsp;&nbsp;&nbsp;Lens {<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Frustum &lt;left&gt; &lt;right&gt; &lt;bottom&gt; &lt;top&gt; &lt;znear&gt;  &lt;zfar&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;}</p>
+<p>Frustum&rsquo;s parameter format is same as glFrustum()  function in OpenGL.<br>
+  Model/View matrix is defined in an &quot;Offset&quot; block,  which may contain &quot;Translate&quot; and &quot;Rotate&quot; lines in order of operations.</p>
+<p>&nbsp;&nbsp;&nbsp;&nbsp;Offset {<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transform &lt;x&gt; &lt;y&gt; &lt;z&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotate &lt;angle (degree)&gt; &lt;x&gt; &lt;y&gt;  &lt;z&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;}</p>
+<p>These Translate and Rotate formats are also  same as glTranslate*() and glRotate*() functions in OpenGL.</p>
+<p> This View matrix file format is a subset of  Open Producer&rsquo;s camera configuration file. So you can use it as it is in Open Scene  Graph based applications.</p>
+<a name="build"><h2>Build</h2></a>
+    <h3>Dependencies</h3>
+    <p>To build ProjectionDesigner by yourself, you have to prepare the following libraries.</p>
+    <dl>
+        <dt>Trolltech Qt library ver. 4.2 or later
+        <dd>Download the latest Trolltech Qt library from its web site: <a href="http://www.trolltec.com/">http://www.trolltec.com/</a>.</dd>
+</dl>
+
+
+<a name="todo"><h2>Todo</h2></a>
+<ul>
+<li>More stability. Avoid redundant renderings. 
+</ul>
+
+
+<a name="future"><h2>Future Plans</h2></a>
+<ul>
+<li>Automatic calibration (for free) ?
+<li>etc...
+</ul>
+
+
+<a name="change"><h2>Change Log</h2></a>
+<ul>
+<li>2007/4/10 Projection Designer version 1.1.0. Remove GLRC, DevIL, Glee and libQGLViewer dependencies. Split the scene renderings as a plug-in.
+<li>2006/7/15 Projection Designer version 1.0.0, the first public release.
+</ul>
+</DIV>
+<!-- //#main.pad --></DIV><!-- //#main --></DIV><!-- //#left-container.sub -->
+
+<!-- ************* left menu ****************-->
+<DIV id=left>
+<DIV class=menuBox>
+
+<h2>contents</h2>
+<ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#features">Main Features</a></li>
+<li><a href="#screenshots">Screenshots</a></li>
+<li><a href="#author">Author</a></li>
+<li><a href="#platform">Platform</a></li>
+<li><a href="#licence">Licence</a></li>
+<li><a href="#download">Download</a></li>
+<li><a href="#preparation">Preparation</a></li>
+<li><a href="#tutorial">Tutorial</a></li>
+<li><a href="#build">Build</a></li>
+<li><a href="#todo">Todo</a></li>
+<li><a href="#future">Future Plans</a></li>
+<li><a href="#change">Change Log</a></li>
+</ul>
+</DIV><!-- //#menuBox -->
+</DIV><!-- //#left -->
+</DIV><!-- //#left-container -->
+
+
+<DIV id=right-container>
+<!-- ************* menu right ****************-->
+<!-- //#right -->
+</DIV>
+<!-- //#container -->
+
+<DIV class=clear></DIV>
+
+<DIV id=footer>
+<address>
+This site copyright (c) 2006 Toshiyuki Takahei.
+</address></DIV>
+
+</BODY></HTML>
+
Index: projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.7.10.old
===================================================================
--- projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.7.10.old	(revision 3)
+++ 	(revision )
@@ -1,844 +1,0 @@
-<?xml version="1.0" encoding="shift_jis"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.10"
-	Name="projdesigner_default"
-	SccProjectName=""
-	SccLocalPath="">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="."
-			IntermediateDirectory=".\release"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="/I$(QTDIR)\mkspecs\win32-msvc -Zm200 "
-				Optimization="1"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="$(QTDIR)\include\QtCore,$(QTDIR)\include\QtGui,$(QTDIR)\include\QtOpenGL,$(QTDIR)\include\QtXml,$(QTDIR)\include,..\..,$(QTDIR)\include\ActiveQt,release,."
-				PreprocessorDefinitions="_LIB;UNICODE;QT_LARGEFILE_SUPPORT;QT_NO_DEBUG;QT_STATICPLUGIN;QT_PLUGIN;QT_XML_LIB;QT_OPENGL_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;WIN32"
-				StringPooling="TRUE"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="TRUE"
-				RuntimeTypeInfo="TRUE"
-				PrecompiledHeaderFile=".\release/defaultplugin.pch"
-				AssemblerListingLocation=".\release/"
-				ObjectFile=".\release/"
-				ProgramDataBaseFileName=".\release/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				CompileAs="0"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="..\..\projdesigner\plugins\defaultplugin.lib"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1033"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="."
-			IntermediateDirectory=".\debug"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalOptions="/I$(QTDIR)\mkspecs\win32-msvc -Zm200 "
-				Optimization="4"
-				AdditionalIncludeDirectories="$(QTDIR)\include\QtCore,$(QTDIR)\include\QtGui,$(QTDIR)\include\QtOpenGL,$(QTDIR)\include\QtXml,$(QTDIR)\include,..\..,$(QTDIR)\include\ActiveQt,debug,."
-				PreprocessorDefinitions="_LIB;UNICODE;QT_LARGEFILE_SUPPORT;QT_STATICPLUGIN;QT_PLUGIN;QT_XML_LIB;QT_OPENGL_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;WIN32"
-				RuntimeLibrary="3"
-				RuntimeTypeInfo="TRUE"
-				PrecompiledHeaderFile=".\debug/defaultplugin.pch"
-				AssemblerListingLocation=".\debug/"
-				ObjectFile=".\debug/"
-				ProgramDataBaseFileName=".\debug/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				DebugInformationFormat="3"
-				CompileAs="0"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="..\..\projdesigner\plugins\defaultplugind.lib"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1033"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
-			<File
-				RelativePath="DefaultCubemapSceneContent.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultCubemapSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultEmptySceneContent.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultEmptySceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultModelSceneContent.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultModelSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultplugin.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultProjectorData.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultProjectorWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultTeapotSceneContent.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultTeapotSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="glm.c">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl">
-			<File
-				RelativePath="DefaultCubemapSceneContent.h">
-			</File>
-			<File
-				RelativePath="DefaultCubemapSceneWidget.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultCubemapSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultCubemapSceneWidget.h&quot; -o &quot;release\moc_DefaultCubemapSceneWidget.cpp&quot;
-"
-						Outputs="release\moc_DefaultCubemapSceneWidget.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultCubemapSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultCubemapSceneWidget.h&quot; -o &quot;debug\moc_DefaultCubemapSceneWidget.cpp&quot;
-"
-						Outputs="debug\moc_DefaultCubemapSceneWidget.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultEmptySceneContent.h">
-			</File>
-			<File
-				RelativePath="DefaultEmptySceneWidget.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultEmptySceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultEmptySceneWidget.h&quot; -o &quot;release\moc_DefaultEmptySceneWidget.cpp&quot;
-"
-						Outputs="release\moc_DefaultEmptySceneWidget.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultEmptySceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultEmptySceneWidget.h&quot; -o &quot;debug\moc_DefaultEmptySceneWidget.cpp&quot;
-"
-						Outputs="debug\moc_DefaultEmptySceneWidget.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultModelSceneContent.h">
-			</File>
-			<File
-				RelativePath="DefaultModelSceneWidget.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultModelSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultModelSceneWidget.h&quot; -o &quot;release\moc_DefaultModelSceneWidget.cpp&quot;
-"
-						Outputs="release\moc_DefaultModelSceneWidget.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultModelSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultModelSceneWidget.h&quot; -o &quot;debug\moc_DefaultModelSceneWidget.cpp&quot;
-"
-						Outputs="debug\moc_DefaultModelSceneWidget.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultplugin.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on defaultplugin.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;defaultplugin.h&quot; -o &quot;release\moc_defaultplugin.cpp&quot;
-"
-						Outputs="release\moc_defaultplugin.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on defaultplugin.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;defaultplugin.h&quot; -o &quot;debug\moc_defaultplugin.cpp&quot;
-"
-						Outputs="debug\moc_defaultplugin.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultProjectorData.h">
-			</File>
-			<File
-				RelativePath="DefaultProjectorWidget.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultProjectorWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultProjectorWidget.h&quot; -o &quot;release\moc_DefaultProjectorWidget.cpp&quot;
-"
-						Outputs="release\moc_DefaultProjectorWidget.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultProjectorWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultProjectorWidget.h&quot; -o &quot;debug\moc_DefaultProjectorWidget.cpp&quot;
-"
-						Outputs="debug\moc_DefaultProjectorWidget.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="DefaultTeapotSceneContent.h">
-			</File>
-			<File
-				RelativePath="DefaultTeapotSceneWidget.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultTeapotSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultTeapotSceneWidget.h&quot; -o &quot;release\moc_DefaultTeapotSceneWidget.cpp&quot;
-"
-						Outputs="release\moc_DefaultTeapotSceneWidget.cpp"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running MOC on DefaultTeapotSceneWidget.h"
-						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultTeapotSceneWidget.h&quot; -o &quot;debug\moc_DefaultTeapotSceneWidget.cpp&quot;
-"
-						Outputs="debug\moc_DefaultTeapotSceneWidget.cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="glm.h">
-			</File>
-		</Filter>
-		<Filter
-			Name="Form Files"
-			Filter="ui">
-			<File
-				RelativePath="defaultcubemapscenewidget.ui">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultcubemapscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultcubemapscenewidget.h
-"
-						Outputs=".\ui_defaultcubemapscenewidget.h"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultcubemapscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultcubemapscenewidget.h
-"
-						Outputs=".\ui_defaultcubemapscenewidget.h"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultemptyscenewidget.ui">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultemptyscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultemptyscenewidget.h
-"
-						Outputs=".\ui_defaultemptyscenewidget.h"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultemptyscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultemptyscenewidget.h
-"
-						Outputs=".\ui_defaultemptyscenewidget.h"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultmodelscenewidget.ui">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultmodelscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultmodelscenewidget.h
-"
-						Outputs=".\ui_defaultmodelscenewidget.h"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultmodelscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultmodelscenewidget.h
-"
-						Outputs=".\ui_defaultmodelscenewidget.h"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultprojectorwidget.ui">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultprojectorwidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultprojectorwidget.h
-"
-						Outputs=".\ui_defaultprojectorwidget.h"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultprojectorwidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultprojectorwidget.h
-"
-						Outputs=".\ui_defaultprojectorwidget.h"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="defaultteapotscenewidget.ui">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultteapotscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultteapotscenewidget.h
-"
-						Outputs=".\ui_defaultteapotscenewidget.h"/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Running UIC on defaultteapotscenewidget.ui"
-						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultteapotscenewidget.h
-"
-						Outputs=".\ui_defaultteapotscenewidget.h"/>
-				</FileConfiguration>
-			</File>
-		</Filter>
-		<Filter
-			Name="Generated"
-			Filter="">
-			<File
-				RelativePath="debug\moc_DefaultCubemapSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_DefaultCubemapSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="debug\moc_DefaultEmptySceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_DefaultEmptySceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="debug\moc_DefaultModelSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_DefaultModelSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="debug\moc_defaultplugin.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_defaultplugin.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="debug\moc_DefaultProjectorWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_DefaultProjectorWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="debug\moc_DefaultTeapotSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="release\moc_DefaultTeapotSceneWidget.cpp">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						Optimization="1"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions=""/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="ui_defaultcubemapscenewidget.h">
-			</File>
-			<File
-				RelativePath="ui_defaultemptyscenewidget.h">
-			</File>
-			<File
-				RelativePath="ui_defaultmodelscenewidget.h">
-			</File>
-			<File
-				RelativePath="ui_defaultprojectorwidget.h">
-			</File>
-			<File
-				RelativePath="ui_defaultteapotscenewidget.h">
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
Index: projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.SPUERSTNIX.Torben.user
===================================================================
--- projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.SPUERSTNIX.Torben.user	(revision 3)
+++ 	(revision )
@@ -1,65 +1,0 @@
-<?xml version="1.0" encoding="shift_jis"?>
-<VisualStudioUserFile
-	ProjectType="Visual C++"
-	Version="8,00"
-	ShowAllFiles="false"
-	>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			>
-			<DebugSettings
-				Command=""
-				WorkingDirectory=""
-				CommandArguments=""
-				Attach="false"
-				DebuggerType="3"
-				Remote="1"
-				RemoteMachine="SPUERSTNIX"
-				RemoteCommand=""
-				HttpUrl=""
-				PDBPath=""
-				SQLDebugging=""
-				Environment=""
-				EnvironmentMerge="true"
-				DebuggerFlavor=""
-				MPIRunCommand=""
-				MPIRunArguments=""
-				MPIRunWorkingDirectory=""
-				ApplicationCommand=""
-				ApplicationArguments=""
-				ShimCommand=""
-				MPIAcceptMode=""
-				MPIAcceptFilter=""
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Win32"
-			>
-			<DebugSettings
-				Command=""
-				WorkingDirectory=""
-				CommandArguments=""
-				Attach="false"
-				DebuggerType="3"
-				Remote="1"
-				RemoteMachine="SPUERSTNIX"
-				RemoteCommand=""
-				HttpUrl=""
-				PDBPath=""
-				SQLDebugging=""
-				Environment=""
-				EnvironmentMerge="true"
-				DebuggerFlavor=""
-				MPIRunCommand=""
-				MPIRunArguments=""
-				MPIRunWorkingDirectory=""
-				ApplicationCommand=""
-				ApplicationArguments=""
-				ShimCommand=""
-				MPIAcceptMode=""
-				MPIAcceptFilter=""
-			/>
-		</Configuration>
-	</Configurations>
-</VisualStudioUserFile>
Index: projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.WIEGTNIX.Torben.user
===================================================================
--- projectionDesigner/tag/ProjectionDesigner_1.1.5/projdesignerplugins/defaultplugin/defaultplugin.vcproj.WIEGTNIX.Torben.user	(revision 3)
+++ 	(revision )
@@ -1,65 +1,0 @@
-<?xml version="1.0" encoding="shift_jis"?>
-<VisualStudioUserFile
-	ProjectType="Visual C++"
-	Version="8,00"
-	ShowAllFiles="false"
-	>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			>
-			<DebugSettings
-				Command=""
-				WorkingDirectory=""
-				CommandArguments=""
-				Attach="false"
-				DebuggerType="3"
-				Remote="1"
-				RemoteMachine="WIEGTNIX"
-				RemoteCommand=""
-				HttpUrl=""
-				PDBPath=""
-				SQLDebugging=""
-				Environment=""
-				EnvironmentMerge="true"
-				DebuggerFlavor=""
-				MPIRunCommand=""
-				MPIRunArguments=""
-				MPIRunWorkingDirectory=""
-				ApplicationCommand=""
-				ApplicationArguments=""
-				ShimCommand=""
-				MPIAcceptMode=""
-				MPIAcceptFilter=""
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Win32"
-			>
-			<DebugSettings
-				Command=""
-				WorkingDirectory=""
-				CommandArguments=""
-				Attach="false"
-				DebuggerType="3"
-				Remote="1"
-				RemoteMachine="WIEGTNIX"
-				RemoteCommand=""
-				HttpUrl=""
-				PDBPath=""
-				SQLDebugging=""
-				Environment=""
-				EnvironmentMerge="true"
-				DebuggerFlavor=""
-				MPIRunCommand=""
-				MPIRunArguments=""
-				MPIRunWorkingDirectory=""
-				ApplicationCommand=""
-				ApplicationArguments=""
-				ShimCommand=""
-				MPIAcceptMode=""
-				MPIAcceptFilter=""
-			/>
-		</Configuration>
-	</Configurations>
-</VisualStudioUserFile>
Index: projectionDesigner/trunk/CHANGES
===================================================================
--- projectionDesigner/trunk/CHANGES	(revision 4)
+++ projectionDesigner/trunk/CHANGES	(revision 4)
@@ -0,0 +1,123 @@
+================================================================================
+
+TOC
+  0 Wishlist
+  I Changes from version  1.0.99 to 1.1.50
+  II. General Changes
+  III. File-specific Changes
+
+================================================================================
+0. Wishlist
+
+- Internationalization: englisch, German
+- Helpbrowser for the Helpsite
+- Adding Testpattern (isogonal Checkerboard / Grid) which are independent from projector alignment and fixed and isogonal to the view point. (Implementation in channel.cpp, same idea like overlayimage, but mathematical calculated image.)
+
+
+================================================================================
+
+Bugfixing:
+- Overlay images are now working in local/server and client mode
+- Screen models are now displayed on the clients immediate after connecting (previous the server needed to load a _new_ model to trigger the clients)
+- If a Screen model file (but defined in a project file) does not exist, a error message is given and a new project started instead of exiting the application without message. 
+- in client mode with screen model, a sync (called by the menu entry) led to a black screen on all clients. This is fixed.
+
+Ergonomics:
+- Filter invalid filenames from screen model loader. This way immediate application shutdown is prevented: On invalid screen model filename: filename is cleared, model not loaded and user informed via message box.
+- All "Open file" dialogues now using the recent filename as default.
+- All menu entries are now available via shortcut. The shortcuts for distortion mode, blend mode and preferences are application wide (independent from window)
+- Icons for easier identification added.
+
+Functional Improvements:
+- Added "About Qt" to the help menu to make the information about used Qt-Version available.
+
+Miscellaneous:
+- compiled against Qt 4.5.1
+
+Knowing Issues:
+- Only screen models consisting of surfaces are possible. Screens of (even thin) solids lead to unusable distortionmaps.
+
+=======================================================================
+II. General Changes:
+
+* The include of <glx.h> and <glxext.h> are replaced by an include og <GL/gl.h>,
+  with a define og GL_GLEXT_PROTOTYPES to enable the use of the ...EXT
+  prototypes.
+
+* The types GLRC_RTT_FBO and GLRC_RTT_COPYSUBTEX are supported. The types 
+  GLRC_RTT_PBUFFER_RTT and GLRC_RTT_PBUFFER are not. So the include of
+  "PBuffer.h" becomes windows-specific (not yet implemented with the linux 
+  version).
+
+* export() methods are renamed in export_dataset(), because 'export' is a 
+  reserved keyword.
+
+* Under linux, files are case-sensitive, so includes are corrected when it is 
+  necessary.
+
+* The default rendering becomes GLRC_RTT_AUTO instead of GLRC_RTT_PBUFFER_RTT
+  (which are unavailable under linux).
+
+* The QProjectorWindow() calls are changed, in order to open a new window
+  (otherwise the window opens in the OpenGL Viewer under linux if parent is 
+  getMainWindow()). 0 is used instead.
+
+* Under linux, a switch on a variable of type enum generates some warnings if 
+  all values are not switched, or of there is no default case. That's why 
+  switch-cases are fullfilled.
+
+* Files CHANGES, README and TODO are added.
+
+================================================================================
+
+III. File-specific Changes:
+
+* glrc/Compositor.cpp:
+  - The printShaderInfoLog procedure was declared as static but not defined
+    (this causes a compilation error).
+
+* glrc/glrc.cpp:
+  - Glee include missed.
+  - glrcDeleteCompositors(): the 'compositors' parameter is unused.
+
+* glrc/glrc.h:
+  - The DLL definitions are windows-specific.
+
+* glrc/rgbe.c:
+  - A warning correction (conversion between signed/unsigned).
+
+* projdesigner/include/Channel.h:
+  - Some methods were unused.
+
+* projdesigner/include/Scene.h:
+  - The gridsize attribute is converted from int to float, which seems more 
+    coherent.
+
+* projdesigner/include/glm/glm.h:
+  - This is a header file, so include definitions are added (#define __GLM_C__)
+  - As this is a C++ header file, 'extern "C"' is added to respect the 
+    convention calls.
+
+* projdesigner/main.cpp:
+  - Under linux, when using glut, the initialisation is necessary, even if it is
+    only glutWireTeapot.
+  - stricmp() is replaced by strcasecmp() for UNIX compilation.
+
+* projdesigner/src/Exporter.cpp:
+  - The color value is an integer, to avoid many warnings.
+
+* projdesigner/src/ProjectionModel.cpp:
+  - ProjectionModel::updateViewAndOffscreens(): 'pChannels' parameter was unused.
+
+* projdesigner/src/glm/glm.c:
+  - A fprintf() call is modified to avoid a compilation warning.
+
+* projdesigner/src/gui/QChannelManagerWidget.cpp:
+  - QChannelManagerWidget::channelTableHeaderClicked(): checkState is 
+    initialised to Qt::Unchecked. This changes nothing, but avoid a compilation 
+    warning. 
+
+* projdesigner/src/gui/QDesignViewWidget.cpp:
+  - Some implicit casts are resolved, to avoid compilation warnings.
+  - bCapsLock was unused, so it is put between the following
+    #ifdef/#endif(WIN32). But it really seems to be unused.
Index: projectionDesigner/trunk/INSTALL
===================================================================
--- projectionDesigner/trunk/INSTALL	(revision 4)
+++ projectionDesigner/trunk/INSTALL	(revision 4)
@@ -0,0 +1,44 @@
+The linux version:
+==================
+
+* Introduction
+
+First of all, create two directories! Qt-4.2.2 and usr in your home.
+$HOME/Qt-4.2.2 will be your QTDIR.
+
+Add the following lines to your .bashrc, and source it (or close and reopen your terminal)
+    export QTDIR=~/Qt-4.2.2
+    export PATH=${PATH}:${QTDIR}/bin
+    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${QTDIR}/lib:${HOME}/usr/lib
+
+The Qt compilation will spent almost two hours, so this is the first thing to begin.
+
+During the Qt compilation, you can install GLee and DevIL.
+
+
+* The Qt library
+
+Download (the OpenSource Version) from http://www.trolltech.com/developer/downloads/qt/x11 (careful: about 36Mo)
+
+Uncompress, compile and install Qt in a local directory:
+$ tar zxvf qt-x11-opensource-src-4.2.2.tar.gz
+$ cd qt-x11-opensource-src-4.2.2
+$ ./configure --prefix=$QTDIR # it takes 5mn.
+(type 'yes' at the license question, if you agree)
+$ make # Almost 2 hours but perhaps it is possible to remove some useless content (with the configure options).
+
+There is nothing else to do during the Qt compilation, so you can go and read some Google News.
+
+When Qt Compilation is over, then you can install it:
+$ make install
+
+
+* ProjDesigner
+
+Uncompress, qmake and make it:
+$ tar zxvf projection-designer-linux-rc1.tar.gz
+$ qmake
+$ make
+
+And finally, to test, do not forget to declare that you want to link with glrc:
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PWD}/glrc
Index: projectionDesigner/trunk/Projection Designer.sln
===================================================================
--- projectionDesigner/trunk/Projection Designer.sln	(revision 4)
+++ projectionDesigner/trunk/Projection Designer.sln	(revision 4)
@@ -0,0 +1,34 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "projdesigner", "projdesigner\projdesigner.vcproj", "{4418A7F1-9C0E-31B2-B8A2-913D1394330B}"
+	GlobalSection(Qt) = preSolution
+		Integration = True
+	EndGlobalSection
+	ProjectSection(ProjectDependencies) = postProject
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC} = {6169FA3C-3764-3D1A-80FC-D97551D6C7AC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "projdesigner_default", "projdesignerplugins\defaultplugin\projdesigner_default.vcproj", "{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}"
+	GlobalSection(Qt) = preSolution
+		Integration = True
+	EndGlobalSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{4418A7F1-9C0E-31B2-B8A2-913D1394330B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{4418A7F1-9C0E-31B2-B8A2-913D1394330B}.Debug|Win32.Build.0 = Debug|Win32
+		{4418A7F1-9C0E-31B2-B8A2-913D1394330B}.Release|Win32.ActiveCfg = Release|Win32
+		{4418A7F1-9C0E-31B2-B8A2-913D1394330B}.Release|Win32.Build.0 = Release|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Debug|Win32.Build.0 = Debug|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Release|Win32.ActiveCfg = Release|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: projectionDesigner/trunk/README
===================================================================
--- projectionDesigner/trunk/README	(revision 4)
+++ projectionDesigner/trunk/README	(revision 4)
@@ -0,0 +1,27 @@
+================================================================================
+
+TOC
+
+  I. How to run under linux
+
+================================================================================
+
+I. How to run under linux
+
+To build the Makefiles, type:
+  qmake
+
+To compile the project, type:
+  make
+
+Then you can type:
+  ./projdesigner/projdesigner
+
+To install the project, type:
+  make install
+
+If the project is installed, to run projdesigner, just type:
+  projdesigner
+
+================================================================================
+
Index: projectionDesigner/trunk/TODO
===================================================================
--- projectionDesigner/trunk/TODO	(revision 4)
+++ projectionDesigner/trunk/TODO	(revision 4)
@@ -0,0 +1,81 @@
+================================================================================
+
+* linux: The initial window is to high and I cannot resize it vertically (and it
+  is the same under windows). Perhaps this would be due to a property of some
+  content of the right panel which forbids the window to be smaller (?).
+
+* linux: When maximise the window, the window is flickering, as if the system 
+  was trying to draw the window from the top aligned with the top of the screen,
+  and the next image from the bottom aligned with the bottom of the screen.
+  - maximised_window__bottom_aligned.png : You can see the "Open Window" at the
+    bottom.
+  - maximised_window__top_aligned.png : You cannot see the "Open Window" at the
+    bottom anymore.
+
+* Internalisation : is there something to easily translate the soft?
+
+* linux: I got some strange things with the "-client" option. Perhaps something 
+  due to a wrong management of UTF-8 with Qt. Sometimes the soft did not see the
+  "-" of "-client", so it didn't know that I gave it an option and failed to
+  launch the client app. Perhaps this is due to some treatment of the args in 
+  the qt init, or in the glutInit (see CHANGES for the added glutInit call).
+
+* projdesigner/src/gui/QConnectionDialog.cpp is not used, and include a 
+  non-existent header. I remove it?
+
+* linux: glrc: PBuffers are not supported yet.
+
+[n/m|p] :
+n is 'how the new fonctionnality, or the bug, is important'. 5 is an essential task. 0 is almost an option.
+m is 'how long is the development of the functionnality, or the correction of the bug'. 5 is a very long development (in weeks), whereas 0 is a very small development (one line of code to change for instance).
+p is n-m
+Tasks are sorted by p (and next by inverse n).
+
+Plugin Milestone:
+* [4/1|3] Remove the extra plugin from here and rename it RSA_projdesigner_plugin or something like this.
+* [5/2|3] Check that all modifications are taken into account by the slaves (in order to avoid the manual "remote synchro")
+          Note XBL: I need a remote config. This can come from Channel::updatePluginData that doen't call Channel::updateData. This happens if the is_equal_to is matching. If is_equal_to is buggy, the call will imply such behavior.
+                    This needs a bench, with debugs in different part: when grid.setup is over, when the signal is emitted, when it is catched by the connected channel, and when the DomElement is built and sent.
+* [3/1|2] Under windows, the lib directory is not a good idea. Something should be added to specify the plugin path.
+* [1/0|1] Rename DefaultPluginData in DefaultProjectorData
+* [2/1|1] Use some slots to connect the m_grid to the widgets.
+* [4/3|1] Use the arrows to control a "control point" and shift and control to increase/decrease the speed, and tab to change the point.
+* [5/4|1] The warp does not work under linux.
+          Note XBL: It works for me. It can come from a network issue or an extension issue... This needs some debug.
+* [5/4|1] The blend export doesn't work (careful, this is a linux port bug).
+          Note XBL: This should be fixed by the Toshiyuki's latest version.
+* [0/0|0] Check if the RTT work under windows (add it to the TODO list if not)
+* [1/1|0] Check box Fullscreen: not ok. It does something but not the good one. Need a Sync.
+* [2/2|0] There is a synchro problem when adding a grid (the grid is not added on clients).
+* [2/2|0] Create a plugin template which will not be in the ProjDesigner project.
+* [2/2|0] Add some validators in the plugins widgets
+* [3/3|0] Use the calibrate button to add a calibration plugin
+* [5/5|0] Add a contextual menu.
+* [0/1|-1] It will be nice, not to print "Default Plugin" when the plugin is alone... this is true for the distinction between Projector and Scene (since extraplugin doesn't implement any scene, the basicplugin's scene should not be annoted "Default Plugin", because they can not come from another plugin!).
+* [1/2|-1] Add a .projdesigner directory or something else (using QSettings) and store where are the plugins.
+* [1/2|-1] When a value is entered, and RETURN is pressed, the value should be selected, in order to be able to type another one immediatly.
+* [1/2|-1] In a line edit, CTRL+Z does not take modif into account, RETURN must be pressed.
+* [2/3|-1] The "Window" should be bigger. I can zoom but not move (add scrollbars?)
+* [0/2|-2] Add the Id property to each file managed (cpp/h)
+* [0/2|-2] FR: Detail esthetique : je peux afficher le widget du plugin par defaut dans le channelwidget lorsque tout le composant est disabled.
+* [0/2|-2] Add a right-click on the grids with [Edit|Delete|Clone|Up|Down].
+* [0/2|-2] Add a right-click on the '-' button of the grids with [Remove selected|Remove all]
+* [0/2|-2] Add the full name of a recent file in the ToolTip of the 'file' menu
+* [1/3|-2] Split interfaces.h in interfaces.h, PluginInterface.h and SceneInterface.h.
+* [1/3|-2] Intercept when the user changes the projector or the scene, ask the plugin if the projector or the scene is the default one and warn the user if there is a risk to loose some contents.
+* [1/3|-2] Use app.arguments() to get arguments and uses POPT to deal with them. Be careful to the compatibility.
+* [0/3|-3] It would be great to have an incremental autosave.
+* [0/4|-4] Add the possibility to combine the scenes, with the same kind of control than the channel manager. A kind of scene manager. Perhaps is it not possible (because of the "Scene Viewer")
+* [0/5|-5] Some ZFighting seems to be observed with the glm renderer.
+* [x/x|x] Before release the milestone: Check compatibility
+* [x/x|x] Before release the milestone: Check save/load operations
+* [x/x|x] Before release the milestone: Check import operations
+* [x/x|x] Before release the milestone: Check MEMORY MANAGEMENT
+* [x/x|x] Check that the plugin version is working through the network.
+
+Fisheye Milestone:
+* [5/3|2] Add the fisheye plugin.
+
+Warp edition
+* [x/x|x] Add the CTRL+Z management
+
Index: projectionDesigner/trunk/doc/base.css
===================================================================
--- projectionDesigner/trunk/doc/base.css	(revision 4)
+++ projectionDesigner/trunk/doc/base.css	(revision 4)
@@ -0,0 +1,230 @@
+@charset "UTF-8";
+
+HTML {
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	BACKGROUND: #FFF
+	PADDING-BOTTOM: 0px;
+	MARGIN: 0px;
+	PADDING-TOP: 0px;
+}
+
+BODY {
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	FONT-SIZE: small;
+	BACKGROUND: #FFF;
+	PADDING-BOTTOM: 0px;
+	MARGIN: 1px;
+	PADDING-TOP: 0px;
+	FONT-FAMILY: "Trebuchet MS", Verdana, "Lucida Sans", "Lucida Sans Unicode", Arial, Sans-Serif;
+}
+
+/*
+"",inherit
+}
+*/
+
+.clear {
+	CLEAR: both
+}
+.pad {
+	padding: 5px;
+
+}
+
+.menuBox {
+	padding: 5px;
+	border: 1px solid #DDD;
+	margin: 0px 10px 10px 10px;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	text-align: left;
+}
+
+.menuBox ul {
+  margin: 0px 0px 10px 5px;
+@padding: 10px 30px;
+	list-style-image: url('./images/li_bl.gif');
+}
+
+.menuBox h2 {
+	margin: 10px 0px 10px 0px;
+	padding: 3px 3px 3px 8px;
+	font-size: 100%;
+	color: #8F8F8F;
+	background: #FFF url(./images/gray_stripe.png);
+	background-repeat: repeat-x;
+	letter-spacing: 0pt;
+	border-left: 4px solid #CCC;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+
+P {
+	PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 5px; MARGIN: 0px; PADDING-TOP: 0px
+}
+
+a {
+	color: #9c9c9c;
+	text-decoration: none;
+	font-weight: bold;
+}
+a:hover {
+	color: #E92;
+	text-decoration: underline;
+}
+
+a:visited {
+  color: #9c9c9c;
+}
+
+a:visited:hover {
+	color: #E92;
+	text-decoration: underline;
+}
+
+#header {
+	width: 100%;
+	height: 95px;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	margin: 0px;
+}
+
+#header img {
+	margin-left: -5px;
+	margin-top: 17px;
+}
+
+
+
+
+
+p,dl {
+	margin: 5px 10px 10px 20px;
+}
+dt {
+	margin-left: 10px;
+	font-weight: bold;
+	color: #888;
+}
+dd {
+	margin-bottom: 5px;
+}
+
+
+/* padding for IE indent problem. */
+
+
+
+
+
+#container {
+	PADDING-TOP: 0px;
+	PADDING-RIGHT: 0px;
+	PADDING-LEFT: 0px;
+	PADDING-BOTTOM: 0px;
+	WIDTH: 100%;
+	background: #FFF;
+	margin-top: 5px;
+}
+
+#container img {
+	margin: 5px;
+	padding: 5px;
+	border: 1px solid #DDD;
+}
+
+
+
+#left-container {
+	background: #CCC url(./images/stripe.gif);
+	FLOAT: left;
+	WIDTH: 100%;
+	MARGIN-RIGHT: -200px;
+	padding-top: 10px;
+}
+
+#left-container .sub {
+	FLOAT: right;
+	MARGIN-LEFT: -200px;
+	WIDTH: 100%;
+}
+
+#right-container {
+	padding-top: 10px;
+}
+
+
+#main {
+	PADDING: 0px;
+	BACKGROUND: #EEE;
+	MARGIN: 0px 200px 150px 200px;
+	border: 1px solid #D2D2D2;
+}
+
+#main ul {
+  margin: 0px 0px 10px 10px;
+@padding: 10px 30px;
+  list-style-image: url('./images/li_bl.gif');
+}
+
+
+#main h2 {
+	margin: 5px 0px 10px 0px;
+	padding: 7px;
+	font-size: 110%;
+	color: #8F8F8F;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	letter-spacing: 1pt;
+	border-left: 6px solid #BBB;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+#main h3 {
+	margin: 5px 0px 5px 11px;
+	padding: 3px 3px 3px 6px;
+	font-size: 105%;
+	color: #8F8F8F;
+	letter-spacing: 1pt;
+	background: #FFF url(./images/bg_gray.png);
+	border-left: 5px solid #CCC;
+	border-right: 1px solid #DDD;
+	border-bottom: 1px solid #DDD;
+}
+
+#main h4 {
+	margin: 5px 5px 5px 20px;
+	padding: 2px 2px 2px 10px;
+    letter-spacing: 1pt;
+	font-size: 100%;
+	color: #666;
+	border-bottom: 2px dotted #CCC;
+}
+
+
+#left {
+	CLEAR: all;
+
+	FLOAT: left;
+	WIDTH: 200px;
+}
+#right {
+
+	FLOAT: right;
+	WIDTH: 200px;
+}
+
+#footer {
+	BACKGROUND: #E5E5E5;
+	width: 100%;
+	background: #FFF url(./images/bg_gray.png);
+	background-repeat: repeat-x;
+	text-align: center;
+}
+
+
Index: projectionDesigner/trunk/doc/index.html
===================================================================
--- projectionDesigner/trunk/doc/index.html	(revision 4)
+++ projectionDesigner/trunk/doc/index.html	(revision 4)
@@ -0,0 +1,318 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html lang="ja">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Projection Designer</title>
+	<meta http-equiv="content-style-type" content="text/css">
+	<meta http-equiv="content-language" content="en">
+	<link rel="stylesheet" href="base.css" type="text/css">
+    <style type="text/css">
+<!--
+.style2 {font-size: 36px}
+.style4 {font-size: 16px}
+-->
+    </style>
+</head>
+<body>
+
+<DIV id=header>
+  <p>
+    <!--<H1>Inneroptics CSS Layouts</H1>-->
+    </p>
+  <p><span class="style2">Projection Designer </span><span class="style4">ver.1.1.0<br>
+  Projection Environment Setup Tool</span></p>
+</DIV>
+
+<!-- ************* body ****************-->
+<DIV id=container>
+<DIV id=left-container>
+<DIV class=sub>
+
+<DIV id=main>
+<DIV class=pad>
+
+<a name="overview"><h2>Overview</h2></a>
+<p><strong>ProjectionDesigner</strong> is a setup tool for distortion correction and edge blending in  multiple projection theater environments with various types of screen shapes.  With this tool you can setup virtual projectors and a virtual screen in 3d  environment to simulate the projection. You should run this tool in the actual  environment to confirm the result of the simulation in real-time. After the  setup, this tool exports the setup result as a <strong>&lsquo;Projection data set&rsquo;</strong> &ndash; <strong>Distortion  map image</strong>, <strong>Blending map image</strong> and <strong>View matrix file</strong>. This data set  is basic information for projection in your environment.</p>
+<p>You can use a movie converter tool with  this data set to split and distort movie files for each projector. If you can  link GLRC(OpenGL rendering composite library) with your OpenGL application, the  application will load this data set for distortion correction and edge blending  in real-time. With a special OpenGL replacement driver GLWare, you can also  make these corrections for many OpenGL based applications without their source  code.</p>
+<p>This projection data set is simple,  universal and not depends on implementation of applications. So you can make  OpenGL or DirectX based 3d application, converter tools and etc based on this  data set. From content creator&rsquo;s point of view, you can expect that each theater  has its own projection data set made by its user or vendor. So you can focus  your energy on creating immersive content itself, not depending on actual theater  environments.</p>
+<p>ProjectionDesigner is a primitive, manual  based setup tool. Basically it has no auto calibration functions such as  (patented) camera-projector feedback algorithm. It&rsquo;s important that there is at  least one way to make the projection data set for free. If you want more  automated, easy way to achieve the result, you should look for other tools.</p>
+<a name="mainfeatures">
+<h2>Main features </h2>
+</a>
+<ul>
+  <li>Virtual screen and projectors simulation  in real-time 3d environment.</li>
+  <li>Server / client synchronization for  multiple PC projection environments.</li>
+  <li>Supports plane, box, dome and any  polygon-based shape screen.</li>
+  <li>Projector&rsquo;s position, direction, field of  view, aspect ratio lens shift is configurable.</li>
+  <li>2d-based direct distortion / blend map  shape manipulation.</li>
+  <li>Image overlaying on projection image for  reference.</li>
+  <li>Simple Wavefront (.obj) format model  importer for sample scene.</li>
+  <li>Open format. Open source. Freely  available!</li>
+</ul>
+
+
+
+<a name="screenshots">
+<h2>Screenshots</h2>
+</a>
+<p><a href="images/projdesigner.png" target="_blank"><img src="images/projdesigner_s.png" alt="ProjectionDesigner GUI" width="128" height="96" border="0"></a> <a href="images/onscreen.png" target="_blank"><img src="images/onscreen_s.png" alt="Projected image on screen" width="128" height="96" border="0"></a> <a href="images/distortwindow.png" target="_blank"><img src="images/distortwindow_s.png" alt="Distortion design" width="96" height="76" border="0"></a> <a href="images/blendwindow.png" target="_blank"><img src="images/blendwindow_s.png" alt="Blend map design" width="96" height="76" border="0"></a></p>
+
+
+
+<a name="author">
+<h2>Author</h2>
+</a>
+<p>Toshiyuki Takahei (takahei&lt;at&gt;orihalcon.jp)</p>
+
+
+
+<a name="platform"><h2>Platform</h2></a>
+<p>Windows 2000/XP</p>
+<a name="licence"><h2>Licence</h2></a>
+<p>General Public Licence (GPL) / Commercial License (Dual License) </p>
+
+
+
+<a name="download"><h2>Download</h2></a>
+<p><a href="http://www.orihalcon.jp/download/projdesigner_1.1.0.zip">Source and Windows binary</a></p>
+
+
+<a name="preparation"><h2>Preparation</h2></a>
+<h3>Hardware setup </h3>
+
+<p>When you setup the projection system with  ProjectionDesigner, you should run it in actual projectors and PCs. In the  following adjustment step, you&rsquo;ll put virtual projectors and a screen strictly  same as the actual ones, and project the simulated distortion images with the  actual hardware to check the precise of result for more detail adjustment. For  this reason, you need actual number of projectors to use, and one more screen  to display the ProjectionDesigner user interface. You can use graphic cards  with multiple display output, and networked PCs to prepare the enough number of  displays.</p>
+<p>ProjectionDesigner heavily uses OpenGL  functions, especially off-screen rendering features such as a P-Buffer. You  should use the latest graphic card and powerful PC you have. You should also  install the latest graphic card driver.</p>
+<p>To minimize the number of variable projector&rsquo;s  parameters, you should disable projector&rsquo;s own distortion correction. You  should also set the same parameters to zoom angle, lens shift, brightness and  so on for all projectors you use. </p>
+<h3>Network setup</h3>
+<p>If you want to use ProjectionDesigner as server /  client system over LAN environment, prepare your PC to be able to connect each  other, and open a socket port (default port number is 55555) in firewall. I  recommend to put ProjectionDesigner in a share folder where all PCs can access,  and use the same program file. In this case, if you need many connections more  than Window&rsquo;s limitation (ex. 8 in WindowsXP), you should put the files in  non-Windows based NAS.</p>
+<h3>Execute and Exit program</h3>
+<h4>Boot as Standalone / Server</h4>
+<p>When you use ProjectionDesigner only in one  PC, or use it on a server PC to do adjustment work, run <strong>projdesigner.exe</strong> program without arguments. If you want to specify a custom port  number, use <strong>[-portno]</strong> option.</p>
+<p><strong>projdesigner.exe [-portno 12345]</strong></p>
+<h4>Boot as Client</h4>
+<p>When you use ProjectionDesigner on a client  PC which connected to projectors, run <strong>projdesigner.exe</strong> program with <strong>[-client]</strong> option. You should give a server address with <strong>[-address]</strong> option, and a custom port number with <strong>[-portno]</strong> option.</p>
+<p><strong>projdesigner.exe &ndash;client &ndash;address 192.168.0.10 [-portno  12345]</strong></p>
+<p>If the client program can not connect a server  program, it tries to connect the server again and again. So you can boot a  server after clients. But when you change number of clients or their host name,  you should execute <strong>[File]</strong> &gt; <strong>[Sync Clients]</strong> in menu for synchronization. It  will be described in detail later. </p>
+<h4>Exit the program</h4>
+
+<p>You can quit standalone / server program by <strong>[File] &gt; [Exit]</strong> in menu or click <strong>[X]</strong> button on the title bar. If your client program is displayed  in full screen mode and menus are hidden, hit <strong>[Alt]  + [Return]</strong> to cancel the full screen mode. You can also quit  server and all client programs at once by <strong>[File]  &gt; [Exit All]</strong> in server&rsquo;s menu. When you close the standalone /  server program, all unsaved data will be discarded. Needless to say, save your  data before exit the program!</p>
+
+
+<a name="tutorial"><h3>Tutorial</h3></a>
+<p>In the following section describes each step of adjustment with ProjectionDesigner.</p>
+<h4>Execute programs</h4>
+<p>At first run <strong>projdesigner.exe</strong> on a server PC which has a screen to display the  ProjectionDesigner&rsquo;s adjustment user interface. Then run <strong>projdesigner.exe</strong> on client PCs with <strong>[-client]</strong> option and <strong>[-address]</strong> option with the server&rsquo;s address as a client mode. If  the clients successfully connect to the server, a message &ldquo;Connected to server:  server address&rdquo; is displayed in their log area.</p>
+<h4>Setup screen shape</h4>
+
+
+
+<p>Click <strong>[Screen]</strong> tab in GUI panel, select a shape type in <strong>[Shape]</strong> group&rsquo;s <strong>[Type]</strong> combo box. Set screen&rsquo;s size depends on its shape type (unit is meter). In some  screen shape, you can set wire frame resolution. If you can mark reference  points on screen surface, or if your screen has some geometrical hint for  reference, it&rsquo;s highly useful for later adjustment to set the wire frame  resolution to match the reference points. Set your screen&rsquo;s position, rotation  and scale in the <strong>[Screen]</strong> tab&rsquo;s <strong>[Transform]</strong> group. Check <strong>[Wire  frame]</strong> to display screen&rsquo;s wire frame grid.</p>
+<h4>Add a Channel</h4>
+<p>Let&rsquo;s add the first Channel. <strong>&lsquo;Channel&rsquo;</strong> means a set which consists of one projector (&lsquo;<strong>Projector&rsquo;</strong>) and rendering view (<strong>&lsquo;View&rsquo;</strong>) for it. This first channel becomes the basis of the following  other channel, so setup this channel accurately as much as you can.</p>
+<p>Click <strong>[Channels]</strong> tab in GUI panel, click <strong>[Add]</strong> button  to add a channel. In [Name] field you can set name of channel. Channel name must  be unique among all channels.</p>
+<h4>Setup for projection</h4>
+<p>If you&rsquo;re connecting the first channel&rsquo;s  projector to the server PC, click <strong>[Open Window&hellip;]</strong> button at the bottom of <strong>[Channels]</strong> tab. When a <strong>Projector Window</strong> appears, move  it to the screen for projection, click somewhere in the window, then hit <strong>[Alt]  + [Return]</strong> to toggle it to full screen mode.<img src="images/remotesettings.png" alt="Remote Settings" width="233" height="155" align="right"></p>
+<p>If you want to use a client PC for the  first channel, click <strong>[Remote Settings]</strong> in <strong>[Channels] </strong>tab, and set client  PC&rsquo;s network host name in <strong>[Host name]</strong> field. Then click <strong>[Full screen]</strong> check box to full screen mode. After that, select <strong>[File]  &gt; [Sync Clients]</strong> in menu to synchronize between  server and clients.</p>
+<p>Now you have ProjectionDesigner&rsquo;s main window and one  other screen for projection of the first channel. In the following steps, you  should adjust parameters by actually projecting the channel image on the  screen. </p>
+<h4>Setup Projector's parameters</h4>
+<p><img src="images/projectorsettings.png" alt="Projector Settings" width="234" height="304" align="right">Click <strong>[Channels]</strong> tab in GUI panel, then click <strong>[Projector]</strong> to open a sub panel. In this panel, set <strong>[FOV]</strong> (projector&rsquo;s vertical field of view in degree) and <strong>[Aspect]</strong> (projector&rsquo;s aspect ratio, width/height. Ex. 1.33333  in XGA) values refer to its spec sheet. If your projector projects image to  upper direction (most projectors do it), you should set <strong>[Off-axis X, Y]</strong> value (offset distance of image center at 1m from the  projector&rsquo;s center). Though these parameters are anytime adjustable in  real-time, but I recommend to set precise values at first, and use the same  value among all projectors.</p>
+<p>Next, let's setup position and direction of the  first channel&rsquo;s Projector. In the 3D area there is a screen and projector&rsquo;s  projection area. Purpose of this step is to make the projector&rsquo;s parameters to  the actual one. But in most case it is difficult to measure the projector&rsquo;s  precise position and direction, you should use wire frame grid to match it to  reference points or geometrical hints.</p>
+<p> You can set parameter values in fields of <strong>[Projector</strong>] sub panel in <strong>[Channels]</strong> tab, or use the following keyboard shortcuts in 3D area. To use keyboard  shortcuts, hit <strong>[Esc]</strong> key first to focus on 3D  area.</p>
+<p> I repeat that precise of first channel&rsquo;s  adjustment effects the following channels. Keep it in mind and setup precisely  as much as you can.</p>
+<p><strong>Shortcut keys in 3D area</strong></p>
+<p><table border="1">
+  <tr>
+    <th>Shortcut</th>
+    <th>Meanings</th>
+  </tr>
+  <tr>
+    <td><strong>Mouse  left drag</strong></td>
+    <td>Rotation  of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>Mouse  right drag </strong></td>
+    <td>Pan  of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>Mouse  wheel</strong></td>
+    <td>Change  distance of 3D view.</td>
+  </tr>
+  <tr>
+    <td><strong>[Cursor  key]</strong></td>
+    <td>Change  direction of Projector / View.*</td>
+  </tr>
+  <tr>
+    <td><strong>[Home][End]</strong></td>
+    <td>Change direction  (roll) of Projector / View.*</td>
+  </tr>
+  <tr>
+    <td><strong>[8][4][6][2]</strong></td>
+    <td>Move Projector /  View horizontally.*</td>
+  </tr>
+  <tr>
+    <td><strong>[9][3]</strong></td>
+    <td>Move  Projector / View vertically.*</td>
+  </tr>
+  <tr>
+    <td><strong>[+][-][*][/]</strong></td>
+    <td>Change  Projector / View &lsquo;s lens shift value.*</td>
+  </tr>
+  <tr>
+    <td><strong>[.][,]</strong></td>
+    <td>Change  Projector / View &lsquo;s field of view.*</td>
+  </tr>
+  <tr>
+    <td><strong>[F1]-[F5]</strong></td>
+    <td>Change 3D view mode.</td>
+  </tr>
+  <tr>
+    <td><strong>[Q]</strong></td>
+    <td>Switch  operation mode between Projector and View.</td>
+  </tr>
+  <tr>
+    <td><strong>[T]</strong></td>
+    <td>Switch  move coordinate between Local and World.</td>
+  </tr>
+  <tr>
+    <td><strong>[Space]</strong></td>
+    <td>Change the current channel.</td>
+  </tr>
+  <tr>
+    <td><strong>[A]</strong></td>
+    <td>Show or hide coordinate axes.</td>
+  </tr>
+  <tr>
+    <td><strong>[G]</strong></td>
+    <td>Show or hide grid frame.</td>
+  </tr>
+  <tr>
+    <td><strong>[I]</strong></td>
+    <td>Show or hide information at upper left corner.</td>
+  </tr>
+  <tr>
+    <td><strong>[Esc]</strong></td>
+    <td>Focus on 3D area.</td>
+  </tr>
+</table>
+</p>
+<p>* marked shortcut  can adjust values in 1/10 accuracy with <strong>[Shift]</strong> key, in 1/100 accuracy with <strong>[Shift] +  [Ctrl]</strong> keys.</p>
+<h4>Setup View parameters</h4>
+<p><img src="images/viewsettings.png" alt="View Settings" width="234" height="247" align="right">After the Projector setup, you need to setup View  parameters. View means rendering area of the scene. In practice, you should adjust  it as a view from the sweet spot (a point where you can see undistorted image  in the theater), covering whole projector&rsquo;s projected area on the screen  surface. <strong>[Channels]</strong> tab in GUI panel has a channel list at the top of it.  In this channel list, click <strong>[P]</strong>(Projector) cell of the current channel twice to make  it gray check, click <strong>[V]</strong>(View) to make it gray check too. Now you can see blue  Projector area and yellow View area on the screen surface. Let&rsquo;s adjust the  yellow area to cover whole blue area. Hit <strong>[Esc]</strong> key to focus on 3D area, <strong>[Q]</strong> key to switch View operation mode. Move the View to  sweet spot where the best view position in the theater (ex. In dome screen, it  should center of the dome &ndash; origin of the coordinate). Then change direction of  the View by <strong>[Cursor key]</strong>,<strong>[Home]</strong>,<strong>[End]</strong> key, and change FOV by <strong>[.]</strong>,<strong>[,]</strong> key to cover the whole blue area. More the View area  becomes closer to Projector area, higher distortion rendering quality you&rsquo;ll get.</p>
+<h4>Save your projection setup data</h4>
+<p>Now you finished the first channel setup. You  should save the current setup data. Select [File] &gt; [Save As] in menu to  save the current data to xml file. Needless to say, you should save data  frequently.</p>
+<h4>Setup other channels</h4>
+<p>For the next step, you should setup the  next channel. In <strong>[Channels]</strong> tab in GUI panel, click <strong>[Add]</strong> button to add a new channel. Added new channel has the same parameter values as  the first channel (last selected channel) as default. It&rsquo;s useful when you  setup left channel after right channel.</p>
+<p>You can setup the new channel same as the  first channel. When you adjust the Projector of the new channel, you&rsquo;ll notify  that when the two projector&rsquo;s projection area are overlapped, edge of the  projection area is visible in another projector&rsquo;s projection image. It will be  helpful hint for precise adjustment. With these hints you may be able to setup  the following channels easier than the first one. But you should keep in mind  that adjustment errors are accumulated in each channel. You still need to work precisely.</p>
+<h4>Test with a sample scene</h4>
+<p><img src="images/channellist.png" alt="Channel List" width="234" height="190" align="right">Now let&rsquo;s see a sample scene with adjusted  distortion correction. In channel list in <strong>[Channels]</strong> tab of GUI panel, make all <strong>[P]</strong>(Projector) and <strong>[V]</strong>(View)  to be unchecked, and make all <strong>[S]</strong>(Scene)  to be checked by clicking header of the channel list. If you setup the  projection correctly, you can see an undistorted teapot model from the sweet  spot in your theater. If you need higher resolution for distortion correction,  select <strong>[Edit] &gt; [Preference&hellip;]</strong> in menu  to open <strong>Preference Dialog</strong>, and then  change <strong>[Size]</strong> value in <strong>[Off-screen  Scene Rendering]</strong> group.</p>
+<p>You can freely move the sample scene  object. Select <strong>[Window] &gt; [Scene Viewer&hellip;]</strong> in  menu to open <strong>Scene Viewer Window</strong>. In this  window, you can rotate the scene by mouse left drag, and change distance from  the object by mouse wheel.</p>
+<h4>Warp distortion for detail adjustment</h4>
+<p><img src="images/distortwindow_m.png" alt="Distortion map design" width="240" height="190" align="right">In spite of the careful setup, accumulation  of adjustment, screen shape and lens distortion error may cause small but  unfixable projection error. For these cases, you can use direct image  distortion to tweak the distortion correction. Keep in mind that this direct  tweak does not reflect geometrical information. You must use it for tiny error  only.</p>
+<p>Select <strong>[Channels]</strong> tab in GUI panel, and then check <strong>[Enable]</strong> check  box in <strong>[Warp]</strong> group. Click <strong>[Open Window&hellip;]</strong> button to open <strong>Projector  Window</strong> on the server PC. Since you activated the warp  flag, you&rsquo;ll see yellow control points in the <strong>Projector  Window</strong>. You can tweak the projection image directly by  dragging these yellow control points. If you want more control points, set <strong>[Res.]</strong> value  in <strong>[Warp]</strong> group. Notice that when you change the number of control points, the current  setup of control points will be discarded. You can reset the control points by  clicking <strong>[Reset]</strong> button. </p>
+<h4>Make a blend map</h4>
+<p><img src="images/blendwindow_m.png" alt="Blend map design" width="240" height="190" align="right">When you use multiple projectors, you&rsquo;ll  notice that projector&rsquo;s overlapped area will becomes brighter. To equalize  intensity on the screen surface, you need to make a <strong>blend map</strong> which represents darken overlapped area.</p>
+<p>To make a blend map in ProjectionDesigner,  select <strong>[Edit] &gt; [Blend Map]</strong> in menu  to switch to blend map editing mode. In the actual projection environment, you&rsquo;ll  see the white images of all projectors cause undesirable intensity  distribution. Select a channel to make a blend map in the channel list in <strong>[Channels]</strong> tab, click <strong>[Open Window&hellip;] </strong>button to open <strong>Projector Window</strong>. Click somewhere in the window and hit <strong>[Space]</strong> key to confirm switching selected blend channel name displayed at  the upper left corner. Now select a channel which overlapped on the current  channel by hitting <strong>[Space]</strong> key  some times. You can darken the blend channel by hitting <strong>[B]</strong> key. Adjust the blend value by <strong>[B]</strong>,<strong>[D]</strong> key until achieving flat  intensity distribution on the screen surface.</p>
+<p>You can smooth the blending edge for seamless  intensity distribution. Select <strong>[Edit]  &gt; [Preference&hellip;]</strong> in menu to open <strong>Preference Dialog</strong>, check <strong>[Soft  edge]</strong> in <strong>[Blend  Map]</strong> group. You can also change width and intensity  curve of the blending edge by editing <strong>[Width]</strong> and <strong>[Exponent]</strong> fields.</p>
+<h4>Export the Projection data set</h4>
+<p><img src="images/preferencedialog.png" alt="Preference Dialog" width="343" height="377" align="right">After finishing the projection setup,  export the Projection data set to use it in other applications. Save the  current data at first, then select <strong>[File] &gt; [Export Data set&hellip;]</strong> in menu to export the data set. The Projection data set will be  exported in the same directory as the data file saved like:</p>
+<p>distort_CHANNELNAME.png<br>
+blend_CHANNELNAME.png<br>
+view_CHANNELNAME.cfg</p>
+<p>You can change size of distortion map and  blend map image. Select <strong>[Edit] &gt; [Preference&hellip;]</strong> in menu to open <strong>Preference Dialog</strong>, and then change <strong>[Image size]</strong> value in <strong>[Export]</strong> group. You can also set file name pattern in the <strong>Preference  Dialog</strong>. In the file name pattern setting,  <strong>%CHANNELNAME%</strong> will be replaced to channel name, <strong>%CHANNELINDEX%</strong> to channel  index, <strong>%REMOTEHOST%</strong> to remote host name.</p>
+<p align="right">&nbsp;</p>
+<a name="formats"><h2>Format of Projection data set</h2></a>
+<p>This chapter explains format specifications of the  Projection data set.</p>
+<h3>Distortion map image</h3>
+<p><img src="images/distortmap.png" alt="Distortion map image" width="128" height="128" align="right">In distortion correction, you need to  pre-warp a rendered image to make a projection image on a screen surface  undistorted viewed from a sweet spot in your theater. Distortion map defines  where each pixel in the projection image mapped from undistorted rendered image.  Color value of each pixel in the distortion map image represents normalized  coordinate in the rendered image.</p>
+<p>&nbsp; X =  ( B / 255 + ( R mod 16 ) ) / 16.<br>
+  &nbsp; Y =  ( G / 255+ ( R  / 16 ) ) / 16.</p>
+<p>Here, X and Y is normalized coordinate (0.0-1.0) in  the rendered image, R, G and B is color element value in the distortion map  (0-255). You can use this formula in your shader code or texture mapping  coordinate generation code to realize the distortion correction.</p>
+<h3>Blend map image</h3>
+<p><img src="images/blendmap.png" alt="Blend map image" width="128" height="128" align="right">In multiple projector environments, you need to  darken overlapped area of projectors to flatten intensity on the screen  surface. Blend map represents intensity distribution and color correction for  the projection image. You should multiply this blend map image to projection  image which is pre-warped by the distortion map.</p>
+<h3>View matrix file</h3>
+<p>View matrix file defines View&rsquo;s model/view  matrix and projection matrix of a channel for rendering in your 3D application.</p>
+<p>This file is a simple text file nested by &lsquo;{&lsquo;  and &lsquo;}&rsquo; &nbsp;blocks. The most outer block is &quot;Channel&quot; like this: </p>
+<p>Camera &ldquo;CHANNELNAME&rdquo; { &hellip; }</p>
+<p>In this block, the following &quot;Lens&quot; block represents  a projection matrix of the View.</p>
+<p>&nbsp;&nbsp;&nbsp;&nbsp;Lens {<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Frustum &lt;left&gt; &lt;right&gt; &lt;bottom&gt; &lt;top&gt; &lt;znear&gt;  &lt;zfar&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;}</p>
+<p>Frustum&rsquo;s parameter format is same as glFrustum()  function in OpenGL.<br>
+  Model/View matrix is defined in an &quot;Offset&quot; block,  which may contain &quot;Translate&quot; and &quot;Rotate&quot; lines in order of operations.</p>
+<p>&nbsp;&nbsp;&nbsp;&nbsp;Offset {<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transform &lt;x&gt; &lt;y&gt; &lt;z&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotate &lt;angle (degree)&gt; &lt;x&gt; &lt;y&gt;  &lt;z&gt;<br>
+  &nbsp;&nbsp;&nbsp;&nbsp;}</p>
+<p>These Translate and Rotate formats are also  same as glTranslate*() and glRotate*() functions in OpenGL.</p>
+<p> This View matrix file format is a subset of  Open Producer&rsquo;s camera configuration file. So you can use it as it is in Open Scene  Graph based applications.</p>
+<a name="build"><h2>Build</h2></a>
+    <h3>Dependencies</h3>
+    <p>To build ProjectionDesigner by yourself, you have to prepare the following libraries.</p>
+    <dl>
+        <dt>Trolltech Qt library ver. 4.2 or later
+        <dd>Download the latest Trolltech Qt library from its web site: <a href="http://www.trolltec.com/">http://www.trolltec.com/</a>.</dd>
+</dl>
+
+
+<a name="todo"><h2>Todo</h2></a>
+<ul>
+<li>More stability. Avoid redundant renderings. 
+</ul>
+
+
+<a name="future"><h2>Future Plans</h2></a>
+<ul>
+<li>Automatic calibration (for free) ?
+<li>etc...
+</ul>
+
+
+<a name="change"><h2>Change Log</h2></a>
+<ul>
+<li>2007/4/10 Projection Designer version 1.1.0. Remove GLRC, DevIL, Glee and libQGLViewer dependencies. Split the scene renderings as a plug-in.
+<li>2006/7/15 Projection Designer version 1.0.0, the first public release.
+</ul>
+</DIV>
+<!-- //#main.pad --></DIV><!-- //#main --></DIV><!-- //#left-container.sub -->
+
+<!-- ************* left menu ****************-->
+<DIV id=left>
+<DIV class=menuBox>
+
+<h2>contents</h2>
+<ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#features">Main Features</a></li>
+<li><a href="#screenshots">Screenshots</a></li>
+<li><a href="#author">Author</a></li>
+<li><a href="#platform">Platform</a></li>
+<li><a href="#licence">Licence</a></li>
+<li><a href="#download">Download</a></li>
+<li><a href="#preparation">Preparation</a></li>
+<li><a href="#tutorial">Tutorial</a></li>
+<li><a href="#build">Build</a></li>
+<li><a href="#todo">Todo</a></li>
+<li><a href="#future">Future Plans</a></li>
+<li><a href="#change">Change Log</a></li>
+</ul>
+</DIV><!-- //#menuBox -->
+</DIV><!-- //#left -->
+</DIV><!-- //#left-container -->
+
+
+<DIV id=right-container>
+<!-- ************* menu right ****************-->
+<!-- //#right -->
+</DIV>
+<!-- //#container -->
+
+<DIV class=clear></DIV>
+
+<DIV id=footer>
+<address>
+This site copyright (c) 2006 Toshiyuki Takahei.
+</address></DIV>
+
+</BODY></HTML>
+
Index: projectionDesigner/trunk/projdesigner/include/Channel.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Channel.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Channel.h	(revision 4)
@@ -0,0 +1,362 @@
+// -*- mode:c++ -*-
+#ifndef _CHANNEL_H_
+#define _CHANNEL_H_
+
+#include <QtXml>
+#include <QtOpenGL>
+
+#include "interfaces.h"
+#include "Frustum.h"
+#include "Screen.h"
+
+class QGLPixelBuffer;
+
+namespace projection
+{
+class ProjectionModel;
+class Warp;
+
+//! Channel draw mode
+enum CHANNEL_DRAWMODE
+{
+    CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP,  //!< Draw distortion map for designing.
+    CHANNEL_DRAWMODE_EXPORT_DISTORTIONMAP,  //!< Draw distortion map for exporting.
+    CHANNEL_DRAWMODE_DESIGN_BLENDMAP,       //!< Draw blend map for designing.
+    CHANNEL_DRAWMODE_EXPORT_BLENDMAP        //!< Draw blend map for exporting.
+};
+
+/**
+ * Channel class. It contains projector and view data.
+ */
+class Channel : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pModel Projection model.
+     */
+    Channel(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Channel();
+
+    /**
+     * Render the scene to a texture.
+     */
+    void renderSceneToViewBuffer();
+
+    /**
+     * Render the screen viewing from the projector.
+     */
+    void draw(CHANNEL_DRAWMODE drawMode);
+
+    /**
+     * Draw projector and view frustum shape objects.
+     *
+     * @param bSelected True to draw with selection highlight.
+     */
+    void drawFrustums(bool bSelected=false);
+
+    /**
+     * Set channel name.
+     *
+     * @param name Name of the channel.
+     */
+    void setName(const QString& name);
+
+    /**
+     * Retrieve name of the channel.
+     */
+    QString getName() const;
+
+    /**
+     * Show or hide the name of the channel in the projector view.
+     *
+     * @param bShow True to show the name of the channel, false to hide.
+     */
+    void setOverlayName(bool bShow);
+
+    /**
+     * Check whether the name of the channel is shown or not.
+     *
+     * @return True if the name of the channel.
+     */
+    bool getOverlayName() const;
+
+    /**
+     * Set host name of the remote host PC to show this channel.
+     *
+     * @param hostName Host name of the remote host PC.
+     */
+    void setRemoteHostName(const QString& hostName);
+
+    /**
+     * Retrieve host name of the remote host PC to show this channel.
+     *
+     * @return Host name of the remote host PC.
+     */
+    QString getRemoteHostName() const;
+
+    /**
+     * Enable or disable the full-screen mode at remote host PC.
+     *
+     * @param bFullScreen True to display this channel in full-screen mode at remote host PC.
+     */
+    void setRemoteFullScreen(bool bFullScreen);
+
+    /**
+     * Check whether this channel is full-screen or not at remote host PC.
+     *
+     * @return True to display this channel in full-screen mode at remote host PC.
+     */
+    bool getRemoteFullScreen() const;
+
+    /**
+     * Screen index for multi-monitor remote host PC.
+     *
+     * @param screenIndex Screen index to display this channel.
+     */
+    void setRemoteScreen(int screenIndex);
+
+    /**
+     * Retrieve screen index for multi-monitor remote host PC.
+     *
+     * @return Screen index to display this channel.
+     */
+    int  getRemoteScreen() const;
+
+    /**
+     * Set file name of image to overlay in the projection window.
+     *
+     * @param fileName File name to overlay in the projection window
+     */
+    void setOverlayImageFileName(const QString& fileName);
+
+    /**
+     * Retrieve file name of image  to overlay in the projection window.
+     *
+     * @return File name to overlay in the projection window
+     */
+    QString getOverlayImageFileName() const;
+
+    /**
+     * Retrieve projector frustum object.
+     *
+     * @return Projector frustum object.
+     */
+    ProjectorData* getProjector();
+
+    /**
+     * Retrieve view frustum object.
+     *
+     * @return View frustum object.
+     */
+    Frustum* getView();
+
+	void setProjector(ProjectorInterface *projector_interface=NULL, const QString& projector_name="");
+	void setProjector(const QString& projector_fullname);
+
+    /**
+     * Show or hide the projected scene in DesignView.
+     *
+     * @param bShow True to display the projected scene in DesignView.
+     */
+    void setShowProjectedScene(bool bShow);
+
+    /**
+     * Check whether the projected scene is shown in DesignView.
+     *
+     * @return True if the projected scene is shown in DesignView.
+     */
+    bool getShowProjectedScene() const;
+
+    /**
+     * Show projector window of this channel.
+     */
+    void showProjectorWindow();
+
+    /**
+     * Fit the view frustum to projection area on the screen surface.
+     *
+     * @return True if successfully fitted.
+     */
+    bool fitView();
+
+    /**
+     * Retrieve the rendered view texture object ID.
+     *
+     * @return Rendered view texture object ID.
+     */
+    unsigned int getViewTexture();
+
+    /**
+     * Reconstruct the off-screen buffer.
+     */
+    void reconstructBuffer();
+
+    /**
+     * Retrieve distortion warp class instance.
+     *
+     * @return Distortion warp class instance.
+     */
+    Warp* getDistWarp() const;
+
+    /**
+     * Retrieve blending warp class instance.
+     *
+     * @return Blending warp class instance.
+     */
+    Warp* getBlendWarp() const;
+
+    /**
+     * Retrieve the current (distortion / blending) warp class instance.
+     *
+     * @return Current (distortion / blending) warp class instance.
+     */
+    Warp* getCurrentWarp() const;
+
+    /**
+     * Enable or disable distortion warping.
+     *
+     * @param bEnabled True to enable the distortion warping, false to disable.
+     */
+    void setDistWarpEnabled(bool bEnabled);
+
+    /**
+     * Check whether the distortion warping is enabled or not.
+     *
+     * @return True if the distortion warping is enabled.
+     */
+    bool getDistWarpEnabled() const;
+
+    /**
+     * Discard the off-screen buffer object for warping.
+     */
+    void clearWarpBuffer();
+
+    /**
+     * Set blending factor of the specified channel for exporting a blend map.
+     *
+     * @param name Name of channel to set blending factor.
+     * @param factor Blending factor (0.0-1.0).
+     */
+    void setBlendFactor(const QString& name, float factor);
+
+    /**
+     * Retrieve the blending factor of the specified channel.
+     *
+     * @param name Name of channel to retrieve the blending factor.
+     * @return Blending factor of the specified channel.
+     */
+    float getBlendFactor(const QString& name) const;
+
+    /**
+     * Export projection settings to file.
+     *
+     * @param fileName File name of the projection settings to save.
+     * @return True if successfully exported.
+     */
+    bool exportDataset(const QString& fileName);
+
+    /**
+     * Assignment operator.
+     *
+     * @param chan Assignment source channel.
+     */
+    Channel& operator=(const Channel& chan);
+
+	void setProjectorTransformMatrix(const TransformMatrix& matrix);
+	TransformMatrix& getProjectorTransformMatrix(void); // <-- not const because of TransformMatrix::getMatrix() that should be const!
+	void setViewProjectionMatrix(const ProjectionMatrix& matrix);
+	void setViewTransformMatrix(const TransformMatrix& matrix);
+
+    /**
+     * Restore the channel data from XML data.
+     *
+     * @param element Parent XML element of the channel data.
+     */
+    bool initFromDOMElement(const QDomElement& element, const QString& version);
+
+    /**
+     * Store the current channel data as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current channel data as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+public slots:
+
+    /**
+     * Called when channel, projector or view frustum is changed.
+     * Always render the scene to the off-screen buffer...
+     */
+    void updateData();
+
+	void updatePluginData(const ProjectorData& data);
+
+private:
+
+    /**
+     * Retrieve (or create if not exist) off-screen buffer object for warping.
+     *
+     * @return Off-screen buffer object for warping.
+     */
+    QGLPixelBuffer* getWarpBuffer();
+
+    /**
+     * Replace pre-defined keyword in file name pattern.
+     *
+     * @param pattern File name pattern.
+     * @return File name pattern whose keywords replaced.
+     */
+    QString replaceKeywordInFileName(const QString& pattern);
+
+private:
+
+    QString m_name;                 //!< Channel name.
+
+    bool    m_bOverlayName;         //!< True to show the channel name.
+    QString m_overlayImageFileName; //!< File name of image to overlay in the projection window.
+    GLuint  m_overlayImageTexIndex; //!< Texture object index of the image to overlay in the projection window.
+    int     m_overlayImageWidth;    //!< Width of image to overlay in the projection window.
+    int     m_overlayImageHeight;   //!< Height of image to overlay in the projection window.
+
+    bool    m_bShowProjectedScene;  //!< True to display the projected scene in DesignView.
+
+    QString m_remoteHostName;       //!< Remote host name to display this channel.
+    bool    m_bRemoteFullScreen;    //!< True to display this channel in full-screen mode at remote host PC.
+    int     m_remoteScreen;         //!< Screen index for multi-monitor remote host PC.
+
+    Frustum m_projector;            //!< Projector settings.
+    Frustum m_view;                 //!< View settings.
+
+    QGLPixelBuffer* m_pWarpBuffer;  //!< Off-screen buffer for distortion map warping.
+    unsigned int m_warpTextureID;   //!< Distortion warping texture object index.
+
+    Warp* m_pDistWarp;              //!< Distortion map warping.
+    bool m_bDistWarpEnabled;        //!< True to enable the distortion map warping.
+
+    Warp* m_pBlendWarp;             //!< Blend map warping.
+
+    QMap<QString, float> m_blendFactors;    //!< Blend factors for exporting a blend map.
+
+    QGLPixelBuffer* m_pSceneBuffer; //!< Off-screen buffer for rendering the scene.
+    unsigned int m_sceneTextureID;  //!< Scene rendered texture object index.
+
+    ProjectionModel* m_pModel;      //!< Projection model.
+
+    TransformMatrix m_projectorTransformMatrix;      //!< Transform matrix of the frustum.
+	ProjectorData *m_projectorData;
+};
+
+};
+
+#endif // _CHANNEL_H_
Index: projectionDesigner/trunk/projdesigner/include/Exporter.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Exporter.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Exporter.h	(revision 4)
@@ -0,0 +1,205 @@
+#ifndef _EXPORTER_H_
+#define _EXPORTER_H_
+
+#include <QtXml>
+
+namespace projection
+{
+
+/**
+ * Projection settings export class.
+ */
+class Exporter
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pModel Projection model.
+     */
+    Exporter(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Exporter();
+
+    /**
+     * Enable or disable soft edge blending.
+     *
+     * @param bSoftEdge True if soft edge blending is enabled.
+     */
+    void setSoftEdge(bool bSoftEdgeBlend);
+
+    /**
+     * Check whether sof edge blending is enabled or not.
+     *
+     * @return True if soft edge blending is enabled.
+     */
+    bool getSoftEdge() const { return m_bSoftEdge; }
+
+    /**
+     * Set width of the soft edge blending.
+     *
+     * @param blendWidth Width of the soft edge blending.
+     */
+    void setBlendEdgeWidth(int blendEdgeWidth);
+
+    /**
+     * Retrieve width of the soft edge blending.
+     *
+     * @return Width of the soft edge blending.
+     */
+    int  getBlendEdgeWidth() const { return m_blendEdgeWidth; }
+
+    /**
+     * Set gamma curve of blend map edge.
+     *
+     * @param gamma Curve exponent of blend map edge.
+     */
+    void setBlendEdgeExponent(float blendEdgeExponent);
+
+    /**
+     * Retrieve curve exponent of blend map edge.
+     *
+     * @return Curve exponent of blend map edge.
+     */
+    float getBlendEdgeExponent() const { return m_blendEdgeExponent; }
+
+    /**
+     * Set width of distortion map to export.
+     *
+     * @param width Width of distortion map to export.
+     */
+    void setExportWidth(int exportWidth);
+
+    /**
+     * Retrieve width of distortion map to export.
+     *
+     * @return Width of distortion map to export.
+     */
+    int  getExportWidth() const { return m_exportWidth; }
+
+    /**
+     * Set height of distortion map to export.
+     *
+     * @param height Height of distortion map to export.
+     */
+    void setExportHeight(int exportHeight);
+
+    /**
+     * Retrieve height of distortion map to export.
+     *
+     * @return Height of distortion map to export.
+     */
+    int  getExportHeight() const { return m_exportHeight; }
+
+    /**
+     * Set file name pattern of distortion map file.
+     *
+     * @param pattern File name pattern of distortion map file.
+     */
+    void setDistortMapFileNamePattern(const QString& pattern) { m_distortMapFileNamePattern = pattern; }
+
+    /**
+     * Retrieve file name pattern of distortion map file.
+     *
+     * @return File name pattern of distortion map file.
+     */
+    QString getDistortMapFileNamePattern() const { return m_distortMapFileNamePattern; }
+
+    /**
+     * Set file name pattern of blend map file.
+     *
+     * @param pattern File name pattern of blend map file.
+     */
+    void setBlendMapFileNamePattern(const QString& pattern) { m_blendMapFileNamePattern = pattern; }
+
+    /**
+     * Retrieve file name pattern of blend map file.
+     *
+     * @return File name pattern of blend map file.
+     */
+    QString getBlendMapFileNamePattern() const { return m_blendMapFileNamePattern; }
+
+    /**
+     * Set file name pattern of rendering matrix file.
+     *
+     * @param pattern File name pattern of view matrix file.
+     */
+    void setViewMatrixFileNamePattern(const QString& pattern) { m_viewMatrixFileNamePattern = pattern; }
+
+    /**
+     * Retrieve file name pattern of view matrix file.
+     *
+     * @return File name pattern of view matrix file.
+     */
+    QString getViewMatrixFileNamePattern() const { return m_viewMatrixFileNamePattern; }
+
+    /**
+     * Export projection settings to file.
+     *
+     * @param fileName File name of the projection settings.
+     * @return True if successfully exported.
+     */
+    bool exportDataset(const QString& fileName);
+
+    /**
+     * Create a color encoded coordinate texture and retrieve its texture object index.
+     *
+     * @return Texture object index of the encoded coordinate texture.
+     */
+    unsigned int getTexCoordColorTexture();
+
+    /**
+     * Create a color encoded coordinate texture (green and blue channel) and retrieve its texture object index.
+     *
+     * @return Texture object index of the encoded coordinate texture (red channel).
+     */
+    unsigned int getTexCoordColorRTexture();
+
+    /**
+     * Create an edge blending texture and retrieve its texture object index.
+     *
+     * @return Texture object index of the edge blending texture.
+     */
+    unsigned int getBlendingAreaTexture();
+
+    /**
+     * Restore the export settings from XML data.
+     *
+     * @param element Parent XML element of the export settings data.
+     */
+    bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current export settings as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current export settings data as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    bool m_bSoftEdge;                       //!< True if soft edge blending is enabled.
+    int m_blendEdgeWidth;                   //!< Width of the soft edge blending.
+    float m_blendEdgeExponent;              //!< Curve exponent of blend map edge.
+    int m_exportWidth;                      //!< Width of distortion map to export.
+    int m_exportHeight;                     //!< Height of distortion map to export.
+    QString m_distortMapFileNamePattern;    //!< File name pattern of distortion map file.
+    QString m_blendMapFileNamePattern;      //!< File name pattern of blend map file.
+    QString m_viewMatrixFileNamePattern;    //!< File name pattern of view matrix file.
+
+    unsigned int m_texCoordColorTexIndex;   //!< Texture object index of the encoded coordinate texture (green and blue channels).
+    unsigned int m_texCoordColorRTexIndex;  //!< Texture object index of the encoded coordinate texture (red channel).
+    unsigned int m_blendAreaTexIndex;       //!< Texture object index of the edge blending texture.
+
+    ProjectionModel* m_pModel;              //!< Projection model.
+};
+
+}; // projection
+
+#endif // _EXPORTER_H_
Index: projectionDesigner/trunk/projdesigner/include/Frustum.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Frustum.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Frustum.h	(revision 4)
@@ -0,0 +1,164 @@
+#ifndef _FRUSTUM_H_
+#define _FRUSTUM_H_
+
+#include <QtXml>
+#include <QColor>
+
+#include "math/ProjectionMatrix.h"
+#include "math/TransformMatrix.h"
+
+namespace projection
+{
+/**
+ * Frustum data class to represent projection area and view frustum.
+ */
+class Frustum : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    /**
+     * Constructor.
+     */
+    Frustum();
+
+    /**
+     * Destructor.
+     */
+    virtual ~Frustum();
+
+    /**
+     * Set projection matrix of the frustum.
+     *
+     * @param matrix Projection matrix of the frustum.
+     */
+    void setProjectionMatrix(const ProjectionMatrix& matrix);
+
+    /**
+     * Retrieve projection matrix of the frustum.
+     *
+     * @return Projection matrix of the frustum.
+     */
+    ProjectionMatrix getProjectionMatrix() const;
+
+    /**
+     * Set transform matrix of the frustum.
+     *
+     * @param matrix Transform matrix of the frustum.
+     */
+    void setTransformMatrix(const TransformMatrix& matrix);
+
+    /**
+     * Retrieve transform matrix of the frustum.
+     *
+     * @return Transform matrix of the frustum.
+     */
+    TransformMatrix getTransformMatrix() const;
+
+    /**
+     * Set color of the frustum shape object.
+     *
+     * @param color Color of the frustum shape object.
+     */
+	void setColor(const QColor& color);
+
+    /**
+     * Retrieve color of the frustum shape object.
+     *
+     * @return Color of the frustum shape object.
+     */
+    QColor getColor() const;
+
+    /**
+     * Show or hide the frustum shape object.
+     *
+     * @param bShow True to show the frustum shape object, false to hide.
+     */
+    void setShow(bool bShow);
+
+    /**
+     * Check whether the frustum shape object is shown or not.
+     *
+     * @return True if the frustum shape object is shown.
+     */
+    bool getShow() const;
+
+    /**
+     * Show or hide the frustum projected area.
+     *
+     * @param bShow True to show the frustum projected area, false to hide.
+     */
+    void setShowArea(bool bShow);
+
+    /**
+     * Check whether the frustum projected area is shown or not.
+     *
+     * @return True if the frustum projected area is shown.
+     */
+    bool getShowArea() const;
+
+    /**
+     * Set far clip plane distance of the frame shape object. It doesn't modify the frustum data.
+     *
+     * @param farDist Far clip plane distance of the frame shape object.
+     */
+    void setVisibleFar(float farDist);
+
+    /**
+     * Retrieve far clip plane distance of the frame shape object.
+     *
+     * @return Far clip plane distance of the frame shape object.
+     */
+    float getVisibleFar() const;
+
+    /**
+     * Draw frustum shape object.
+     *
+     * @param bSelected True to draw with selection highlight.
+     */
+	void draw(bool bSelected=false);
+
+    /**
+     * Assignment operator.
+     *
+     * @param frustum Assignment source frustum.
+     */
+    Frustum& operator=(const Frustum& frustum);
+
+    /**
+     * Restore the frustum data from XML data.
+     *
+     * @param element Parent XML element of the frustum data.
+     */
+    virtual void initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current frustum data as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current frustum data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+signals:
+
+    /**
+     * Notify that the frustum data is changed.
+     */
+    void dataChanged();
+
+protected:
+
+    ProjectionMatrix m_projectionMatrix;    //!< Projection matrix of the frustum.
+    TransformMatrix m_transformMatrix;      //!< Transform matrix of the frustum.
+    bool m_bShow;                           //!< True if the frustum shape object is shown.
+    bool m_bShowArea;                       //!< True if the frustum projected area is shown.
+    float m_visibleFar;                     //!< Far clip plane distance of the frustum shape object.
+	QColor m_color;                         //!< Color of the frustum shape object.
+};
+
+}; // projection
+
+#endif // _FRUSTUM_H_
Index: projectionDesigner/trunk/projdesigner/include/GUIControler.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/GUIControler.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/GUIControler.h	(revision 4)
@@ -0,0 +1,227 @@
+#ifndef _GUICONTROLER_H_
+#define _GUICONTROLER_H_
+
+#include <QList>
+#include <QtXml>
+#include <QKeyEvent>
+
+namespace projection
+{
+class ProjectionModel;
+class Channel;
+class QDesignViewWindow;
+class QDesignViewWidget;
+class QClientWindow;
+class QProjectorWindow;
+class QSceneViewerWindow;
+class QPreferenceDialog;
+class QCalibrationDialog;
+
+/**
+ * GUI control class.
+ */
+class GUIControler
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pModel Projection model.
+     */
+    GUIControler(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~GUIControler();
+
+    /**
+     * Initialize GUIs.
+     *
+     * @param bServer True if this program is a server, false if it is a client.
+     */
+    void init(bool bServer);
+
+    /**
+     * Load projection settings from a file.
+     *
+     * @param fileName File name to load.
+     * @return True if successfully loaded.
+     */
+    bool loadFile(const QString& fileName);
+
+    /**
+     * Save the current projection settings to a file.
+     *
+     * @param fileName File name to save.
+     * @return True if successfully saved.
+     */
+    bool saveFile(const QString& fileName);
+
+    /**
+     * Retrieve main window.
+     *
+     * @return DesignViewWindow in server, ClientWindow in Client.
+     */
+    QWidget* getMainWindow();
+
+    /**
+     * Retrieve QGLWidget for sharing OpenGL context.
+     *
+     * @return QGLWidget for sharing OpenGL context.
+     */
+    QGLWidget* getGLWidget();
+
+    /**
+     * Retrieve DesignView widget.
+     *
+     * @return DesignView widget.
+     */
+    QDesignViewWidget* getDesignView();
+
+    /**
+     * Select a channel.
+     *
+     * @param pChannel Channel object to select.
+     */
+    void selectChannel(Channel* pChannel);
+
+    /**
+     * Remove the specified channel.
+     *
+     * @param pChannel Channel object to remove.
+     */
+    void removeChannel(Channel* pChannel);
+
+    /**
+     * Process key event for channel.
+     *
+     * @param pChannel Channel to process key event.
+     * @param pEvent Key event.
+     */
+    void processChannelKeyEvent(Channel* pChannel, QKeyEvent* pEvent);
+
+    /**
+     * Update the channel list in GUI.
+     */
+    void updateChannelsGUI();
+
+    /**
+     * Update the name of channels in GUI.
+     */
+    void updateChannelNamesGUI();
+
+    /**
+     * Update the channel in GUI.
+     */
+    void updateChannelGUI();
+
+    /**
+     * Update GUI.
+     */
+    void updateGUI();
+
+    /**
+     * Redraw SceneViewer.
+     */
+    void updateSceneViewer();
+
+    /**
+     * Put the camera at the center of the scene.
+     */
+    void sceneCenterView();
+
+    /**
+     * Set camera to view all the scene.
+     */
+    void sceneViewAll();
+
+    /**
+     * Redraw DesignViewWindow and ProjectorWindows.
+     */
+    void updateViews();
+
+    /**
+     * Set scene size for SceneViewer.
+     *
+     * @param radius Radius of the scene.
+     */
+    void setSceneSize(float radius);
+
+    /**
+     * Create (if not exist) and show a ProjectorWindow for the specified channel.
+     *
+     * @param pChannel Channel object for the ProjectorWindow.
+     */
+    void showProjectorWindow(Channel* pChannel);
+
+    /**
+     * Create (if not exist) and show a SceneViewerWindow.
+     */
+    void showSceneViewerWindow();
+
+    /**
+     * Create (if not exist) and show a PreferenceDialog.
+     */
+    void showPreferenceDialog();
+
+    /**
+     * Create (if not exist) and show a CalibrationWindow for the specified channel.
+     *
+     * @param pChannel Channel object for the CalibrationWindow.
+     */
+    void showCalibrationDialog(Channel* pChannel);
+
+    /**
+     * Show an instant message in status bar of the DesignViewWindow.
+     *
+     * @param message Message to show.
+     * @param timeout Time out interval to disappear in micro seconds.
+     */
+    void showStatusBarMessage(const QString& message, int timeout=0);
+
+    /**
+     * Append log to Client Window.
+     *
+     * @param log Log text.
+     */
+    void appendClientLog(const QString& log);
+
+    /**
+     * Close all windows to quit the application.
+     */
+    void closeAllWindows();
+
+    /**
+     * Restore settings of the DesignView and the SceneViewer.
+     *
+     * @param Parent XML element of the DesignView and the SceneViewer settings.
+     */
+    bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current DesignView and SceneViewer as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current DesignView and SceneViewersettings as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc);
+
+protected:
+
+    QDesignViewWindow* m_pDesignViewWindow;         //!< DesignViewWindow.
+    QClientWindow* m_pClientWindow;                 //!< ClientWindow.
+    QList<QProjectorWindow*> m_pProjectorWindows;   //!< ProjectorWindows.
+    QSceneViewerWindow* m_pSceneViewerWindow;       //!< SceneViewerWindow.
+    QPreferenceDialog* m_pPreferenceDialog;         //!< PreferenceDialog.
+
+    QDomElement m_sceneViewerSettings;              //!< SceneViewer settings.
+
+    ProjectionModel* m_pModel;                      //!< Projection Model.
+};
+
+}; // projection
+
+#endif // _GUICONTROLER_H_
Index: projectionDesigner/trunk/projdesigner/include/ProjectionModel.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/ProjectionModel.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/ProjectionModel.h	(revision 4)
@@ -0,0 +1,348 @@
+#ifndef _PROJECTION_MODEL_H_
+#define _PROJECTION_MODEL_H_
+
+#include <QGLWidget>
+#include <QGLPixelBuffer>
+#include <QtXml>
+#include <QList>
+
+#include "Version.h"
+
+#include "interfaces.h"
+
+namespace projection
+{
+class Scene;
+class Screen;
+class Channel;
+class RSync;
+class Exporter;
+class GUIControler;
+
+
+
+//! Default port number.
+#define DEFAULT_PORT_NO 55555
+
+//! Design mode.
+enum DESIGN_MODE
+{
+    DESIGN_MODE_DISTORTIONMAP,  //!< Distortion map design mode.
+    DESIGN_MODE_BLENDMAP        //!< Blend map design mode.
+};
+
+/**
+ * Projection model class. It contains all projection settings.
+ */
+class ProjectionModel : public QObject
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    ProjectionModel();
+
+    /**
+     * Destructor.
+     */
+    virtual ~ProjectionModel();
+
+    /**
+     * Initialize as a server.
+     *
+     * @param portNo Port number.
+     */
+    void initServer(int portNo=DEFAULT_PORT_NO);
+
+    /**
+     * Initialize as a client.
+     *
+     * @param address Client address.
+     * @param portNo Port number.
+     */
+    void initClient(const QString& address=QString::null,
+                    int portNo=DEFAULT_PORT_NO);
+
+    /**
+     * Add a new channel.
+     *
+     * @return New channel.
+     */
+    Channel* addChannel();
+
+    /**
+     * Retrieve the number of the channels.
+     *
+     * @return The number of the channels.
+     */
+    unsigned int getNumChannels() const;
+
+    /**
+     * Retrieve a channel object
+     *
+     * @param index Index of channel to retrieve.
+     * @return Channel object.
+     */
+    Channel* getChannel(int index) const;
+
+    /**
+     * Retrieve Index of the specified channel.
+     *
+     * @param pChannel Channel object.
+     * @return Index of the specified channel.
+     */
+    int getChannelIndex(Channel* pChannel) const;
+
+    /**
+     * Remove the specified channel.
+     *
+     * @param index Index of the channel to remove.
+     */
+    void removeChannel(int index);
+
+    /**
+     * Remove all channels.
+     */
+    void removeAllChannels();
+
+    /**
+     * Select a channel.
+     *
+     * @param pChannel Channel object to select.
+     */
+    void selectChannel(Channel* pChannel);
+
+    /**
+     * Retrieve the selected channel object.
+     *
+     * @return Selected channel object.
+     */
+    Channel* getSelectedChannel() const;
+
+    /**
+     * Select the previous channel.
+     */
+    void selectPreviousChannel();
+
+    /**
+     * Select the next channel.
+     */
+    void selectNextChannel();
+
+    /**
+     * Check whether any channels with the specified name is existing or not.
+     *
+     * @return True if a channel with the specified name is existing.
+     */
+    bool hasChannel(const QString& name) const;
+
+    /**
+     * Create a unique name for specified channel.
+     *
+     * @param name Candidate name of channel. It may not be a unique name.
+     * @param pChannel Channel object to give a name.
+     * @return Unique name for the specified channel.
+     */
+    QString getUniqueName(const QString& name, Channel* pChannel) const;
+
+    /**
+     * Create a projection area texture and retrieve its texture object index.
+     *
+     * @return Texture object index of the projection area texture.
+     */
+    GLuint getProjectorAreaTexture();
+
+    /**
+     * Create a view area texture and retrieve its texture object index.
+     *
+     * @return Texture object index of the view area texture.
+     */
+    GLuint getViewAreaTexture();
+
+    /**
+     * Set design mode.
+     *
+     * @param designMode Design mode.
+     */
+    void setDesignMode(DESIGN_MODE designMode);
+
+    /**
+     * Retrieve the current design mode.
+     *
+     * @param designMode Design mode.
+     */
+    DESIGN_MODE getDesignMode() const;
+
+    /**
+     * Block or unblock to update views.
+     *
+     * @param bBlock True to block updating views.
+     */
+    void setBlockUpdate(bool bBlock);
+
+    /**
+     * Check whether blocking or not update views.
+     *
+     * @return True if blocking to update views.
+     */
+    bool getBlockUpdate() const;
+
+    /**
+     * Redraw all views (DesignViewWindow and ProjectorWindows).
+     */
+    void updateViews();
+
+    /**
+     * Redraw off-screen buffer of the specified channel, then redraw all views.
+     */
+    void updateViewAndOffscreens();
+
+    /**
+     * Load projection settings from a file.
+     *
+     * @param fileName File name to load.
+     * @return True if successfully loaded.
+     */
+    bool loadFile(const QString& fileName);
+
+    /**
+     * Save the current projection settings to a file.
+     *
+     * @param fileName File name to save.
+     * @return True if successfully saved.
+     */
+    bool saveFile(const QString& fileName);
+
+    /**
+     * Restart from a new file.
+     *
+     * @return True if everything is ok.
+     */
+    bool newFile(void);
+
+    /**
+     * Restore the model from XML data.
+     *
+     * @param element Parent XML element of the model data.
+     */
+    bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current model as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen data as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+    /**
+     * Restore projection settings from xml data.
+     *
+     * @param doc XML document to restore the projection settings from.
+     */
+    bool restoreSettings(QDomDocument& doc);
+
+    /**
+     * Store projection settings to xml data.
+     *
+     * @param doc XML document to store the projection settings.
+     */
+    void storeSettings(QDomDocument& doc);
+
+    /**
+     * Retrieve the scene object.
+     *
+     * @return Scene object.
+     */
+    Scene* getScene() const;
+
+    /**
+     * Retrieve the screen object.
+     *
+     * @return Screen object.
+     */
+    Screen* getScreen() const;
+
+    /**
+     * Retrieve the remote state synchronize object.
+     *
+     * @return Remote state synchronize object.
+     */
+    RSync* getRSync() const;
+
+    /**
+     * Retrieve the exporter object.
+     *
+     * @return Exporter object.
+     */
+    Exporter* getExporter() const;
+
+    /**
+     * Retrieve the GUI controler object.
+     *
+     * @return GUI controler object.
+     */
+    GUIControler* getGUI() const;
+
+    /**
+     * Set a GLWidget for the current render context.
+     *
+     * @parma pGLWidget GLWidget of the current render context.
+     */
+    void setRenderContext(QGLWidget* pGLWidget);
+
+    /**
+     * Set a P-Buffer for the current render context.
+     *
+     * @parma pPBuffer P-Buffer of the current render context.
+     */
+    void setRenderContext(QGLPixelBuffer* pPBuffer);
+
+    /**
+     * Activate the current render context.
+     */
+    void activateRenderContext();
+
+#ifdef _DEBUG
+    int m_updateViewsCount;
+    int m_updateOffscreenCount;
+#endif // _DEBUG
+
+    /// Plugins
+    static QList<ProjectorInterface*> projector_interfaces;
+    static QList<SceneInterface*> scene_interfaces;
+    static QDir pluginsDir;
+    static QStringList pluginFileNames;
+
+protected:
+
+    Scene* m_pScene;                //!< Scene object.
+    Screen* m_pScreen;              //!< Screen object.
+
+    QList<Channel*> m_pChannels;    //!< Channel objects.
+    Channel* m_pSelectedChannel;    //!< Selected channel object.
+
+    DESIGN_MODE m_designMode;       //!< Design mode.
+
+    bool m_bBlockUpdate;            //!< True if blocking to update views.
+
+    RSync* m_pRSync;                //!< Remote state synchronize object.
+    Exporter* m_pExporter;          //!< Exporter object.
+    GUIControler* m_pGUI;           //!< GUI controler object.
+
+    GLuint m_projectorAreaTexIndex; //!< Texture object index of the projection area texture.
+    GLuint m_viewAreaTexIndex;      //!< Texture object index of the view area texture.
+
+    QGLWidget* m_pGLWidget;         //!< GLWidget of the current render context.
+    QGLPixelBuffer* m_pPBuffer;     //!< GLPixelBuffer of the current render context.
+
+private:
+    void loadPlugins();
+
+};
+
+}; // projection
+
+#endif // _PROJECTION_MODEL_H_
Index: projectionDesigner/trunk/projdesigner/include/RSync.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/RSync.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/RSync.h	(revision 4)
@@ -0,0 +1,160 @@
+#ifndef _RSYNC_H_
+#define _RSYNC_H_
+
+#include <QtNetwork/QTcpSocket>
+#include <QtNetwork/QTcpServer>
+
+namespace projection
+{
+class ProjectionModel;
+
+//! Remote sync commands.
+enum RSYNC_COMMAND
+{
+    RSYNC_COMMAND_INIT,         //!< Notify new connection.
+    RSYNC_COMMAND_MODEL,        //!< Sync model settings.
+    RSYNC_COMMAND_VIEWPOINT,    //!< Sync viewpoint.
+    RSYNC_COMMAND_SCENE,        //!< Sync scene settings.
+    RSYNC_COMMAND_SCREEN,       //!< Sync screen settings.
+    RSYNC_COMMAND_CHANNEL,      //!< Sync channel settings.
+    RSYNC_COMMAND_GUI,          //!< Sync gui settings.
+    RSYNC_COMMAND_EXPORT,       //!< Sync export settings.
+    RSYNC_COMMAND_RELOAD,       //!< Request to reload all states.
+    RSYNC_COMMAND_EXPORTFILE,   //!< Request to exort projection data.
+    RSYNC_COMMAND_DISCONNECT,   //!< Notify disconnection.
+    RSYNC_COMMAND_END           //!< Request to quit the program.
+};
+
+/**
+ * Remote state synchronize class.
+ */
+class RSync : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pModel Projection model.
+     */
+    RSync(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~RSync();
+
+    /**
+     * Initialize as a server.
+     *
+     * @param portNo Port number.
+     */
+    void initServer(int portNo);
+
+    /**
+     * Initialize as a client.
+     *
+     * @param address Client address.
+     * @param portNo Port number.
+     */
+    void initClient(const QString& address, int portNo);
+
+    /**
+     * Check whether this program is a server or not.
+     *
+     * @return True if this program is a server, false if it is a client.
+     */
+    bool isServer() const { return m_bServer; }
+
+    /**
+     * Retrieve host name of the PC working on.
+     *
+     * @return Host name of the PC working on.
+     */
+    QString getHostName() const { return m_hostName; }
+
+    /**
+     * Retrieve server address to connect.
+     *
+     * @param Server address to connect.
+     */
+    QString getServerAddress() const { return m_serverAddress; }
+
+    /**
+     * Retrieve port number to connect.
+     *
+     * @param Port number to connect.
+     */
+    int getPortNo() const { return m_portNo; }
+
+    /**
+     * Send a sync command to clients.
+     *
+     * @param command Synchronize command.
+     * @param command Synchronize data.
+     */
+    void sendChanges(RSYNC_COMMAND command, const QString& data);
+
+    /**
+     * Send a reload command to clients.
+     */
+    void sendReloadSettings();
+
+    /**
+     * Set sync message blocking.
+     *
+     * @param bBlock True to block sending sync data to clients.
+     */
+    void setBlockSync(bool bBlock);
+
+    /**
+     * Check whether sync message is blocked or not.
+     *
+     * @param bBlock True to block sending sync data to clients.
+     */
+    bool getBlockSync() const;
+
+protected slots:
+
+    /**
+     * Connect to a server.
+     */
+    void connectToServer();
+
+    /**
+     * Called when a new client connects to the server. Send all states to synchronize.
+     */
+    void acceptNewClient();
+
+    /**
+     * Called when a new synchronize message is received.
+     */
+    void recvSettings();
+
+    /**
+     * Called when a network error is occured.
+     */
+    void displayNetworkError(QAbstractSocket::SocketError socketError);
+
+protected:
+
+    bool m_bServer;             //!< True if this program is a server, false if it is a client.
+    QString m_hostName;         //!< Host name of the PC working on.
+    QString m_serverAddress;    //!< Server address to connect.
+    int m_portNo;               //!< Port number to connect.
+
+    QTcpServer* m_pTcpServer;                   //!< Server object.
+    QTcpSocket* m_pTcpClient;                   //!< Client object.
+    QList<QTcpSocket*> m_pClientConnections;    //!< Connection objects.
+    QString m_lastErrorString;                  //!< Last network error string.
+
+    bool m_bBlockSync;          //!< True to block sending sync data to clients.
+
+    ProjectionModel* m_pModel;  //!< Projection model.
+};
+
+}; // projection
+
+#endif // _RSYNC_H_
Index: projectionDesigner/trunk/projdesigner/include/Scene.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Scene.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Scene.h	(revision 4)
@@ -0,0 +1,269 @@
+#ifndef _SCENE_H_
+#define _SCENE_H_
+
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+#include "math/TransformMatrix.h"
+
+#include "interfaces.h"
+
+namespace projection
+{
+class ProjectionModel;
+
+/**
+ * Scene class.
+ */
+class Scene : public QObject
+{
+    Q_OBJECT
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pModel Projection model.
+     */
+    Scene(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Scene();
+
+    /**
+     * Retrieve Projection model.
+     *
+     * @return Projection model.
+     */
+    ProjectionModel* getModel() const;
+
+    /**
+     * Retrieve name of the scene content.
+     *
+     * @param index Index of the scene content.
+     * @return Name of the scene content.
+     */
+    QString getContentName(int index) const;
+
+    /**
+     * Retrieve the number of the scene content.
+     *
+     * @return Number of the scene content.
+     */
+    unsigned int getNumContents() const;
+
+    /**
+     * Retrieve scene content object.
+     *
+     * @param shapeName Name of the scene content object.
+     * @return Scene content object.
+     */
+    SceneContent* getContent(const QString& contentName) const;
+
+    /**
+     * Select scene content by name.
+     *
+     * @param contentName Name of the scene content to select.
+     */
+    void setCurrentContent(const QString& contentName);
+
+    /**
+     * Retrieve the name of the current scene content.
+     *
+     * @return Name of the current scene content.
+     */
+    QString getCurrentContentName() const;
+
+    /**
+     * Retrieve current scene content object.
+     *
+     * @return Current scene content object.
+     */
+    SceneContent* getCurrentContent() const;
+
+    /**
+     * Retrieve viewpoint center of the scene viewer.
+     *
+     * @return Viewpoint center.
+     */
+    gmtl::Vec3f getCameraCenter() const { return m_cameraCenter; }
+
+    /**
+     * Retrieve viewpoint rotation of the scene viewer.
+     *
+     * @return Viewpoint rotation.
+     */
+    gmtl::Quatf getCameraRotation() const { return m_cameraRot; }
+
+    /**
+     * Retrieve viewpoint distance of the scene viewer.
+     *
+     * @return Viewpoint distance from trackball center.
+     */
+    float getCameraDistance() const { return m_cameraDistance; }
+
+    /**
+     * Retrieve viewpoint matrix of the scene viewer.
+     *
+     * @return Viewpoint matrix.
+     */
+    gmtl::Matrix44f getCameraMatrix() const;
+
+    /**
+     * Put the camera at the center of the scene.
+     */
+    void centerView();
+
+    /**
+     * Set camera to view all the scene.
+     */
+    void viewAll();
+
+    /**
+     * Set transform matrix of the scene.
+     *
+     * @param matrix Transform matrix of the scene.
+     */
+    void setMatrix(const TransformMatrix& matrix);
+
+    /**
+     * Retrieve transform matrix of the scene.
+     *
+     * @param Transform matrix of the scene.
+     */
+    const TransformMatrix& getMatrix() const { return m_transformMatrix; }
+
+    /**
+     * Draw the scene content.
+     */
+    void draw();
+
+    /**
+     * Show or hide the scene content in design view.
+     *
+     * @param bShowInDesignView True to show the scene content in design view.
+     */
+    void setShowInDesignView(bool bShowInDesignView);
+
+    /**
+     * Check whether the scene content is shown in design view.
+     *
+     * @return True if the scene content is shown in design view.
+     */
+    bool getShowInDesignView() { return m_bShowInDesignView; }
+
+    /**
+     * Set size of the scene for SceneViewer.
+     *
+     * @param size Size of the scene.
+     */
+    void setSize(float size);
+
+    /**
+     * Retrieve size of the scene.
+     *
+     * @return Size of the scene.
+     */
+    float getSize() const;
+
+    /**
+     * Show or hide a grid frame with the scene content.
+     *
+     * @param bShowGrid True to show a grid frame, false to hide.
+     */
+    void setShowGrid(bool bShowGrid);
+
+    /**
+     * Check whether the grid frame is shown or not.
+     *
+     * @return True if the grid frame is shown.
+     */
+    bool getShowGrid() { return m_bShowGrid; }
+
+    /**
+     * Set size of the grid frame.
+     *
+     * @param gridSize Size of the grid frame.
+     */
+    void setGridSize(float gridSize);
+
+    /**
+     * Retrieve the size of the grid frame.
+     *
+     * @return Size of the grid frame.
+     */
+    float getGridSize() { return m_gridSize; }
+
+    /**
+     * Notify to redraw the screen.
+     */
+    void notifyRedraw();
+
+    /**
+     * Restore the scene content from XML data.
+     *
+     * @param element Parent XML element of the scene content data.
+     */
+    bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current scene content as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current scene content data as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+	/**
+	 * Reset the scene.
+	 */
+	void reset();
+
+public slots:
+
+    /**
+     * Set viewpoint of the scene viewer.
+     *
+     * @param data Viewpoint as XML data.
+     */
+    void setCameraViewpoint(const QString& data);
+
+    /**
+     * Set viewpoint of the scene viewer.
+     *
+     * @param distance Viewpoint rotation.
+     * @param distance Viewpoint center.
+     * @param distance Viewpoint distance from trackball center.
+     */
+    void setCameraViewpoint(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance);
+
+    /**
+     * Update the scene content.
+     *
+     * @param content Scene content from the widget.
+     */
+	void updateSceneContent(const SceneContent& content);
+
+protected:
+
+    TransformMatrix m_transformMatrix;  //!< Transform matrix of the scene.
+    gmtl::Vec3f m_cameraCenter;         //!< View point center.
+    gmtl::Quatf m_cameraRot;            //!< View point rotation.
+    float m_cameraDistance;             //!< View point distance from trackball center.
+    bool m_bShowInDesignView;           //!< True if the scene content is shown in design view.
+    float m_size;                       //!< Size of the scene.
+    bool m_bShowGrid;                   //!< True if the grid frame is shown.
+    float m_gridSize;                   //!< Size of the grid frame.
+
+	QList<SceneContent*> m_pContents;   //!< Scene content objects.
+    SceneContent* m_pCurrentContent;    //!< Current scene content object.
+
+    ProjectionModel* m_pModel;          //!< Projection model.
+};
+
+}; // projection
+
+#endif // _SCENE_H_
Index: projectionDesigner/trunk/projdesigner/include/Screen.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Screen.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Screen.h	(revision 4)
@@ -0,0 +1,228 @@
+#ifndef _SCREEN_H_
+#define _SCREEN_H_
+
+#include "math/TransformMatrix.h"
+
+//! Projection image source.
+enum PROJECT_SOURCE
+{
+	PROJECT_SOURCE_NONE = 0,            //!< Draw the screen only.
+	PROJECT_SOURCE_PROJECTORAREA,       //!< Projected area of the projector.
+	PROJECT_SOURCE_VIEWAREA,            //!< View area of the channel.
+	PROJECT_SOURCE_SCENE,               //!< Scene viewed from the center.
+	PROJECT_SOURCE_EXPORT_DISTORTION,   //!< Color encoded distortion, green and blue channels (internal use only).
+	PROJECT_SOURCE_EXPORT_DISTORTION_R, //!< Color encoded distortion, red channel (internal use only).
+	PROJECT_SOURCE_EXPORT_BLENDING      //!< Edge blend intensity (internal use only).
+};
+
+namespace projection
+{
+class ScreenShape;
+class Channel;
+class ProjectionModel;
+
+/**
+ * Screen class.
+ */
+class Screen : public QObject
+{
+	Q_OBJECT
+
+public:
+
+    /**
+     * Constructor. Screen data / rendering class.
+     *
+     * @param Projection model.
+     */
+    Screen(ProjectionModel* pModel);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Screen();
+
+	/**
+     * Returns a Pointer to the Projection Model.
+     *
+     * @return Pointer to the ProjectionModel
+     */
+	ProjectionModel* getProjectionModel(){return m_pModel;}
+
+    /**
+     * Set transform matrix of the screen.
+     *
+     * @param matrix Transform matrix of the screen.
+     */
+    void setMatrix(const TransformMatrix& matrix);
+
+    /**
+     * Retrieve the transform matrix of the screen.
+     *
+     * @return Transform matrix of the screen.
+     */
+    TransformMatrix getMatrix() const { return m_transformMatrix; }
+
+    /**
+     * Retrieve name of the screen shape.
+     *
+     * @param index Index of the screen shape.
+     * @return Name of the screen shape.
+     */
+	QString getShapeName(int index) const;
+
+    /**
+     * Retrieve the number of the screen shapes.
+     *
+     * @return Number of the screen shapes.
+     */
+    unsigned int getNumShapes() const;
+
+    /**
+     * Retrieve screen shape object.
+     *
+     * @param shapeName Name of the screen shape.
+     * @return Screen shape object.
+     */
+    ScreenShape* getShape(const QString& shapeName) const;
+
+    /**
+     * Select screen shape by name.
+     *
+     * @param shapeName Name of the screen shape to select.
+     */
+	void setCurrentShape(const QString& shapeName);
+
+    /**
+     * Retrieve the name of the current srceen shape.
+     *
+     * @return Name of the current screen shape.
+     */
+    QString getCurrentShapeName() const;
+
+    /**
+     * Retrieve the current screen shape object.
+     *
+     * @return Current screen shape object.
+     */
+    ScreenShape* getCurrentShape() const;
+
+    /**
+     * Retrive the radius of the current screen.
+     *
+     * @return Radius of the current screen.
+     */
+    float getSize() const;
+
+    /**
+     * Show or hide the wire frame mesh of the screen.
+     *
+     * @param bShowFrame True to show the wire frame mesh.
+     */
+	void setShowFrame(bool bShowFrame);
+
+    /**
+     * Check whether the wire frame mesh of the screen is shown or hidden.
+     *
+     * @param bShowFrame True if the wire frame mesh of the screen is shown.
+     */
+    bool getShowFrame() { return m_bShowFrame; }
+
+    /**
+     * Set line width of the wire frame mesh of the screen.
+     *
+     * @param frameLineWidth Line width of the wire frame mesh of the screen.
+     */
+	void setFrameLineWidth(float frameLineWidth);
+
+    /**
+     * Retrieve the line width of the wire frame mesh of the screen.
+     *
+     * @return Line width of the wire frame mesh of the screen.
+     */
+    bool getFrameLineWidth() { return m_frameLineWidth; }
+
+    /**
+     * Set size of the off-screen buffer.
+     *
+     * @param width Width of the off-screen buffer.
+     * @param height Height of the off-screen buffer.
+     */
+    void setBufferSize(int width, int height);
+
+    /**
+     * Retrieve the width of the off-screen buffer.
+     *
+     * @retrieve Width of the off-screen buffer.
+     */
+    int getBufferWidth() const { return m_bufferWidth; }
+
+    /**
+     * Retrieve the height of the off-screen buffer.
+     *
+     * @retrieve Height of the off-screen buffer.
+     */
+    int getBufferHeight() const { return m_bufferHeight; }
+
+    /**
+     * Draw the screen shape object with.
+     *
+     * @param bDepthMaskControl True to use glDepthMask() for blending.
+     */
+    void draw(bool bDepthMaskControl=true);
+
+    /**
+     * Draw the wire frame mesh of the screen.
+     */
+    void drawFrame();
+
+    /**
+     * Draw the screen object with projection texture image of the specified channel.
+     *
+     * @param source Projection image source to draw.
+     * @param pChannel Channel which draws for.
+     */
+    void draw(PROJECT_SOURCE source, Channel* pChannel=NULL);
+
+    /**
+     * Notify to redraw the screen.
+     */
+    void notifyRedraw();
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen data.
+     */
+	bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen data as XML data.
+     */
+	QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+	/**
+	 * Reset the screen.
+	*/
+    void reset();
+
+protected:
+
+	TransformMatrix m_transformMatrix;  //!< Transform matrix of the screen.
+    bool m_bShowFrame;                  //!< True if the wire frame mesh of the screen is shown.
+    float m_frameLineWidth;             //!< Line width of the wire frame mesh of the screen.
+    int m_bufferWidth;                  //!< Width of the off-screen buffer.
+    int m_bufferHeight;                 //!< Height of the off-screen buffer.
+	QList<ScreenShape*> m_pShapes;      //!< Screen shape objects.
+	ScreenShape* m_pCurrentShape;       //!< Current screen shape object.
+
+    ProjectionModel* m_pModel;          //!< Projection model.
+};
+
+}; // projection
+
+#endif // _SCREEN_H_
Index: projectionDesigner/trunk/projdesigner/include/Version.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Version.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Version.h	(revision 4)
@@ -0,0 +1,30 @@
+#ifndef _VERSION_H_
+#define _VERSION_H_
+
+//! Application name.
+#define APPLICATION_NAME "Projection Designer (Plugged-in Version)"
+
+//! Application version.
+#define APPLICATION_VERSION_MAJOR "1"
+#define APPLICATION_VERSION_MINOR "1"
+#define APPLICATION_VERSION_MICRO "50"
+#define APPLICATION_VERSION_NANO  "plugin"
+
+#ifdef APPLICATION_VERSION_NANO
+#  define APPLICATION_VERSION APPLICATION_VERSION_MAJOR "." APPLICATION_VERSION_MINOR "." APPLICATION_VERSION_MICRO "." APPLICATION_VERSION_NANO
+#else // APPLICATION_VERSION_NANO
+#  define APPLICATION_VERSION APPLICATION_VERSION_MAJOR "." APPLICATION_VERSION_MINOR "." APPLICATION_VERSION_MICRO
+#endif // APPLICATION_VERSION_NANO
+
+/** returns true if v1 is less than v2. */
+bool version_lt(const QString& v1, const QString& v2);
+/** returns true if v1 equal v2. */
+bool version_eq(const QString& v1, const QString& v2);
+/** returns true if v1 is less than or equal v2. */
+bool version_le(const QString& v1, const QString& v2);
+/** returns true if v1 is greater than or equal v2. */
+bool version_ge(const QString& v1, const QString& v2);
+/** returns true if v1 is greater than v2. */
+bool version_gt(const QString& v1, const QString& v2);
+
+#endif // _VERSION_H_
Index: projectionDesigner/trunk/projdesigner/include/Warp.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/Warp.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/Warp.h	(revision 4)
@@ -0,0 +1,80 @@
+#ifndef _WARP_H_
+#define _EARP_H_
+
+#include <QGLWidget>
+#include <QtXml>
+
+namespace projection
+{
+class Warp : public QObject
+{
+public:
+
+    Warp();
+
+    virtual ~Warp();
+
+    void draw(bool bForExport, bool bForBlend);
+    void resize(int width, int height);
+
+    bool pick(int x, int y);
+    bool drag(int x, int y);
+
+    void setEnabled(bool bEnabled);
+    bool getEnabled() const;
+
+    void setNumCtrlPoints(int num);
+    int  getNumCtrlPoints() const;
+
+    void setZoom(float zoom);
+    float getZoom() const;
+
+    void setGridSize(int gridSize);
+    int  getGridSize() const;
+
+    void setShowCtrlPoints(bool bShow);
+    bool getShowCtrlPoints() const;
+
+    void reset();
+
+    /**
+     * Restore the warp data from XML data.
+     *
+     * @param element Parent XML element of the warp data.
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current warp data as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current warp data as XML data.
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+private:
+
+    int  pickCtrlPoint(float x, float y);
+
+private:
+
+    bool m_bEnabled;
+
+    int m_numCtrlPoints;
+    float* m_pCtrlPoints;
+    int m_gridSize;
+    bool m_bShowCtrlPoints;
+    int m_selectedCtrlPoint;
+
+    GLint m_viewport[4];
+    GLdouble m_modelMatrix[16];
+    GLdouble m_projMatrix[16];
+    float m_zoom;
+    int m_lastMouseX;
+    int m_lastMouseY;
+};
+
+}; // projection
+
+#endif // _WARP_H_
Index: projectionDesigner/trunk/projdesigner/include/glm/glm.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/glm/glm.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/glm/glm.h	(revision 4)
@@ -0,0 +1,290 @@
+/*    
+      glm.h
+      Nate Robins, 1997, 2000
+      nate@pobox.com, http://www.pobox.com/~nate
+ 
+      Wavefront OBJ model file format reader/writer/manipulator.
+
+      Includes routines for generating smooth normals with
+      preservation of edges, welding redundant vertices & texture
+      coordinate generation (spheremap and planar projections) + more.
+
+ */
+#ifndef __GLM_H__
+#define __GLM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+#ifndef M_PI
+#define M_PI 3.14159265f
+#endif
+
+#define GLM_NONE     (0)            /* render with only vertices */
+#define GLM_FLAT     (1 << 0)       /* render with facet normals */
+#define GLM_SMOOTH   (1 << 1)       /* render with vertex normals */
+#define GLM_TEXTURE  (1 << 2)       /* render with texture coords */
+#define GLM_COLOR    (1 << 3)       /* render with colors */
+#define GLM_MATERIAL (1 << 4)       /* render with materials */
+
+
+/* GLMmaterial: Structure that defines a material in a model. 
+ */
+typedef struct _GLMmaterial
+{
+  char* name;                   /* name of material */
+  GLfloat diffuse[4];           /* diffuse component */
+  GLfloat ambient[4];           /* ambient component */
+  GLfloat specular[4];          /* specular component */
+  GLfloat emmissive[4];         /* emmissive component */
+  GLfloat shininess;            /* specular exponent */
+} GLMmaterial;
+
+/* GLMtriangle: Structure that defines a triangle in a model.
+ */
+typedef struct _GLMtriangle {
+  GLuint vindices[3];           /* array of triangle vertex indices */
+  GLuint nindices[3];           /* array of triangle normal indices */
+  GLuint tindices[3];           /* array of triangle texcoord indices*/
+  GLuint findex;                /* index of triangle facet normal */
+} GLMtriangle;
+
+/* GLMgroup: Structure that defines a group in a model.
+ */
+typedef struct _GLMgroup {
+  char*             name;           /* name of this group */
+  GLuint            numtriangles;   /* number of triangles in this group */
+  GLuint*           triangles;      /* array of triangle indices */
+  GLuint            material;       /* index to material for group */
+  struct _GLMgroup* next;           /* pointer to next group in model */
+} GLMgroup;
+
+/* GLMmodel: Structure that defines a model.
+ */
+typedef struct _GLMmodel {
+  char*    pathname;            /* path to this model */
+  char*    mtllibname;          /* name of the material library */
+
+  GLuint   numvertices;         /* number of vertices in model */
+  GLfloat* vertices;            /* array of vertices  */
+
+  GLuint   numnormals;          /* number of normals in model */
+  GLfloat* normals;             /* array of normals */
+
+  GLuint   numtexcoords;        /* number of texcoords in model */
+  GLfloat* texcoords;           /* array of texture coordinates */
+
+  GLuint   numfacetnorms;       /* number of facetnorms in model */
+  GLfloat* facetnorms;          /* array of facetnorms */
+
+  GLuint       numtriangles;    /* number of triangles in model */
+  GLMtriangle* triangles;       /* array of triangles */
+
+  GLuint       nummaterials;    /* number of materials in model */
+  GLMmaterial* materials;       /* array of materials */
+
+  GLuint       numgroups;       /* number of groups in model */
+  GLMgroup*    groups;          /* linked list of groups */
+
+  GLfloat position[3];          /* position of the model */
+
+} GLMmodel;
+
+
+/* glmUnitize: "unitize" a model by translating it to the origin and
+ * scaling it to fit in a unit cube around the origin.  Returns the
+ * scalefactor used.
+ *
+ * model - properly initialized GLMmodel structure 
+ */
+GLfloat
+glmUnitize(GLMmodel* model);
+
+/* glmDimensions: Calculates the dimensions (width, height, depth) of
+ * a model.
+ *
+ * model      - initialized GLMmodel structure
+ * dimensions - array of 3 GLfloats (GLfloat dimensions[3])
+ */
+GLvoid
+glmDimensions(GLMmodel* model, GLfloat* dimensions);
+
+/* glmScale: Scales a model by a given amount.
+ * 
+ * model - properly initialized GLMmodel structure
+ * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+ */
+GLvoid
+glmScale(GLMmodel* model, GLfloat scale);
+
+/* glmReverseWinding: Reverse the polygon winding for all polygons in
+ * this model.  Default winding is counter-clockwise.  Also changes
+ * the direction of the normals.
+ * 
+ * model - properly initialized GLMmodel structure 
+ */
+GLvoid
+glmReverseWinding(GLMmodel* model);
+
+/* glmFacetNormals: Generates facet normals for a model (by taking the
+ * cross product of the two vectors derived from the sides of each
+ * triangle).  Assumes a counter-clockwise winding.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmFacetNormals(GLMmodel* model);
+
+/* glmVertexNormals: Generates smooth vertex normals for a model.
+ * First builds a list of all the triangles each vertex is in.  Then
+ * loops through each vertex in the the list averaging all the facet
+ * normals of the triangles each vertex is in.  Finally, sets the
+ * normal index in the triangle for the vertex to the generated smooth
+ * normal.  If the dot product of a facet normal and the facet normal
+ * associated with the first triangle in the list of triangles the
+ * current vertex is in is greater than the cosine of the angle
+ * parameter to the function, that facet normal is not added into the
+ * average normal calculation and the corresponding vertex is given
+ * the facet normal.  This tends to preserve hard edges.  The angle to
+ * use depends on the model, but 90 degrees is usually a good start.
+ *
+ * model - initialized GLMmodel structure
+ * angle - maximum angle (in degrees) to smooth across
+ */
+GLvoid
+glmVertexNormals(GLMmodel* model, GLfloat angle);
+
+/* glmLinearTexture: Generates texture coordinates according to a
+ * linear projection of the texture map.  It generates these by
+ * linearly mapping the vertices onto a square.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmLinearTexture(GLMmodel* model);
+
+/* glmSpheremapTexture: Generates texture coordinates according to a
+ * spherical projection of the texture map.  Sometimes referred to as
+ * spheremap, or reflection map texture coordinates.  It generates
+ * these by using the normal to calculate where that vertex would map
+ * onto a sphere.  Since it is impossible to map something flat
+ * perfectly onto something spherical, there is distortion at the
+ * poles.  This particular implementation causes the poles along the X
+ * axis to be distorted.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmSpheremapTexture(GLMmodel* model);
+
+/* glmDelete: Deletes a GLMmodel structure.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmDelete(GLMmodel* model);
+
+/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+ * Returns a pointer to the created object which should be free'd with
+ * glmDelete().
+ *
+ * filename - name of the file containing the Wavefront .OBJ format data.  
+ */
+GLMmodel* 
+glmReadOBJ(char* filename);
+
+/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+ * a file.
+ *
+ * model    - initialized GLMmodel structure
+ * filename - name of the file to write the Wavefront .OBJ format data to
+ * mode     - a bitwise or of values describing what is written to the file
+ *            GLM_NONE    -  write only vertices
+ *            GLM_FLAT    -  write facet normals
+ *            GLM_SMOOTH  -  write vertex normals
+ *            GLM_TEXTURE -  write texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.
+ */
+GLvoid
+glmWriteOBJ(GLMmodel* model, char* filename, GLuint mode);
+
+/* glmDraw: Renders the model to the current OpenGL context using the
+ * mode specified.
+ *
+ * model    - initialized GLMmodel structure
+ * mode     - a bitwise OR of values describing what is to be rendered.
+ *            GLM_NONE    -  render with only vertices
+ *            GLM_FLAT    -  render with facet normals
+ *            GLM_SMOOTH  -  render with vertex normals
+ *            GLM_TEXTURE -  render with texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.
+ */
+GLvoid
+glmDraw(GLMmodel* model, GLuint mode);
+
+/* glmList: Generates and returns a display list for the model using
+ * the mode specified.
+ *
+ * model    - initialized GLMmodel structure
+ * mode     - a bitwise OR of values describing what is to be rendered.
+ *            GLM_NONE    -  render with only vertices
+ *            GLM_FLAT    -  render with facet normals
+ *            GLM_SMOOTH  -  render with vertex normals
+ *            GLM_TEXTURE -  render with texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLuint
+glmList(GLMmodel* model, GLuint mode);
+
+/* glmWeld: eliminate (weld) vectors that are within an epsilon of
+ * each other.
+ *
+ * model      - initialized GLMmodel structure
+ * epsilon    - maximum difference between vertices
+ *              ( 0.00001 is a good start for a unitized model)
+ *
+ */
+GLvoid
+glmWeld(GLMmodel* model, GLfloat epsilon);
+
+/* glmReadPPM: read a PPM raw (type P6) file.  The PPM file has a header
+ * that should look something like:
+ *
+ *    P6
+ *    # comment
+ *    width height max_value
+ *    rgbrgbrgb...
+ *
+ * where "P6" is the magic cookie which identifies the file type and
+ * should be the only characters on the first line followed by a
+ * carriage return.  Any line starting with a # mark will be treated
+ * as a comment and discarded.   After the magic cookie, three integer
+ * values are expected: width, height of the image and the maximum
+ * value for a pixel (max_value must be < 256 for PPM raw files).  The
+ * data section consists of width*height rgb triplets (one byte each)
+ * in binary format (i.e., such as that written with fwrite() or
+ * equivalent).
+ *
+ * The rgb data is returned as an array of unsigned chars (packed
+ * rgb).  The malloc()'d memory should be free()'d by the caller.  If
+ * an error occurs, an error message is sent to stderr and NULL is
+ * returned.
+ *
+ * filename   - name of the .ppm file.
+ * width      - will contain the width of the image on return.
+ * height     - will contain the height of the image on return.
+ *
+ */
+GLubyte* 
+glmReadPPM(char* filename, int* width, int* height);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // __GLM_H__
Index: projectionDesigner/trunk/projdesigner/include/gmtl/AABox.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/AABox.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/AABox.h	(revision 4)
@@ -0,0 +1,176 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          AABox.h,v
+ * Date modified: 2004/11/22 15:04:05
+ * Version:       1.12
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_AABOX_H_
+#define _GMTL_AABOX_H_
+
+#include <gmtl/Point.h>
+
+namespace gmtl
+{
+   /**
+    * Describes an axially aligned box in 3D space. This is usually used for
+    * graphics applications. It is defined by its minimum and maximum points.
+    *
+    * @param DATA_TYPE     the internal type used for the points
+    *
+    * @ingroup Types
+    */
+   template< class DATA_TYPE >
+   class AABox
+   {
+      // This is a hack to work around a bug with GCC 3.3 on Mac OS X
+      // where boost::is_polymorphic returns a false positive.  The details
+      // can be found in the Boost.Python FAQ:
+      //    http://www.boost.org/libs/python/doc/v2/faq.html#macosx
+#if defined(__MACH__) && defined(__APPLE_CC__) && defined(__GNUC__) && \
+    __GNUC__ == 3 && __GNUC_MINOR__ == 3
+      bool dummy_;
+#endif
+   public:
+      typedef DATA_TYPE DataType;
+
+   public:
+      /**
+       * Creates a new empty box.
+       */
+      AABox()
+         : mMin(0,0,0), mMax(0,0,0), mEmpty(true)
+      {}
+
+      /**
+       * Creates a new box with the given min and max points.
+       *
+       * @param min     the minimum point on the box
+       * @param max     the maximum point on the box
+       *
+       * @pre  all elements of min are less than max
+       * @pre  bot min and max are not zero
+       */
+      AABox(const Point<DATA_TYPE, 3>& min, const Point<DATA_TYPE, 3>& max)
+         : mMin(min), mMax(max), mEmpty(false)
+      {}
+
+      /**
+       * Construcst a duplicate of the given box.
+       *
+       * @param box     the box the make a copy of
+       */
+      AABox(const AABox<DATA_TYPE>& box)
+         : mMin(box.mMin), mMax(box.mMax), mEmpty(box.mEmpty)
+      {}
+
+      /**
+       * Gets the minimum point of the box.
+       *
+       * @return  the min point
+       */
+      const Point<DATA_TYPE, 3>& getMin() const
+      {
+         return mMin;
+      }
+
+      /**
+       * Gets the maximum point of the box.
+       *
+       * @return  the max point
+       */
+      const Point<DATA_TYPE, 3>& getMax() const
+      {
+         return mMax;
+      }
+
+      /**
+       * Tests if this box occupies no space.
+       *
+       * @return  true if the box is empty, false otherwise
+       */
+      bool isEmpty() const
+      {
+         return mEmpty;
+      }
+
+      /**
+       * Sets the minimum point of the box.
+       *
+       * @param min     the min point
+       */
+      void setMin(const Point<DATA_TYPE, 3>& min)
+      {
+         mMin = min;
+      }
+
+      /**
+       * Sets the maximum point of the box.
+       *
+       * @param max     the max point
+       */
+      void setMax(const Point<DATA_TYPE, 3>& max)
+      {
+         mMax = max;
+      }
+
+      /**
+       * Sets the empty flag on this box.
+       *
+       * @param empty   true to make the box empty, false otherwise
+       */
+      void setEmpty(bool empty)
+      {
+         mEmpty = empty;
+      }
+
+   public:
+      /**
+       * The minimum point of the box.
+       */
+      Point<DATA_TYPE, 3> mMin;
+
+      /**
+       * The maximum point on the box.
+       */
+      Point<DATA_TYPE, 3> mMax;
+
+      /**
+       * Flag for empty box. True if the box is empty.
+       */
+      bool mEmpty;
+   };
+
+   // --- helper types --- //
+   typedef AABox<float>    AABoxf;
+   typedef AABox<double>   AABoxd;
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/AABoxOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/AABoxOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/AABoxOps.h	(revision 4)
@@ -0,0 +1,105 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          AABoxOps.h,v
+ * Date modified: 2003/03/17 02:14:48
+ * Version:       1.5
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_AABOXOPS_H_
+#define _GMTL_AABOXOPS_H_
+
+#include <gmtl/AABox.h>
+#include <gmtl/VecOps.h>
+
+namespace gmtl
+{
+
+/** @ingroup Compare AABox 
+ * @name AABox Comparitors
+ * @{
+ */
+
+/**
+ * Compare two AABoxes to see if they are EXACTLY the same. In other words,
+ * this comparison is done with zero tolerance.
+ *
+ * @param b1      the first box to compare
+ * @param b2      the second box to compare
+ *
+ * @return  true if they are equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator==( const AABox<DATA_TYPE>& b1, const AABox<DATA_TYPE>& b2 )
+{
+   return ( (b1.isEmpty() == b2.isEmpty()) &&
+            (b1.getMin() == b2.getMin()) &&
+            (b1.getMax() == b2.getMax()) );
+}
+
+/**
+ * Compare two AABoxes to see if they are not EXACTLY the same. In other words,
+ * this comparison is done with zero tolerance.
+ *
+ * @param b1      the first box to compare
+ * @param b2      the second box to compare
+ *
+ * @return  true if they are not equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator!=( const AABox<DATA_TYPE>& b1, const AABox<DATA_TYPE>& b2 )
+{
+   return (! (b1 == b2));
+}
+
+/**
+ * Compare two AABoxes to see if they are the same within the given tolerance.
+ *
+ * @param b1      the first box to compare
+ * @param b2      the second box to compare
+ * @param eps     the tolerance value to use
+ *
+ * @pre eps must be >= 0
+ *
+ * @return  true if their points are within the given tolerance of each other, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool isEqual( const AABox<DATA_TYPE>& b1, const AABox<DATA_TYPE>& b2, const DATA_TYPE& eps )
+{
+   gmtlASSERT( eps >= 0 );
+   return (b1.isEmpty() == b2.isEmpty()) &&
+          isEqual( b1.getMin(), b2.getMin(), eps ) &&
+          isEqual( b1.getMax(), b2.getMax(), eps );
+}
+/** @} */
+
+}
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngle.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngle.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngle.h	(revision 4)
@@ -0,0 +1,154 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          AxisAngle.h,v
+ * Date modified: 2003/03/30 00:56:58
+ * Version:       1.4
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_AXISANGLE_H_
+#define _GMTL_AXISANGLE_H_
+
+#include <gmtl/Math.h>     // for rotation order
+#include <gmtl/VecBase.h>  // base class of AxisAngle
+#include <gmtl/Vec.h>      // axis data format
+ 
+namespace gmtl
+{
+
+/** AxisAngle: Represents a "twist about an axis"
+ *  AxisAngle is used to specify a rotation in 3-space.
+ *
+ *  To some people this rotation format can be more intuitive to specify than
+ *  Matrix, Quat, or EulerAngle formatted rotation.
+ *
+ *  AxisAngle is very similar to Quat, except it is human readable.
+ *  For efficiency, you should use Quat instead (Quat or Matrix are preferred).
+ *
+ *  The internal data format is an array of 4 DATA_TYPE values.
+ *  Angle is first, the axis is the last 3.
+ *
+ * @pre angles are in radians, the axis is usually normalized by the user.
+ *
+ * @see AxisAnglef, AxisAngled
+ * @see Matrix, Quat, EulerAngle
+ * @ingroup Types
+ */
+template <typename DATA_TYPE>
+class AxisAngle : public VecBase<DATA_TYPE, 4>
+{
+public:
+   enum Params { Size = 4 };
+   
+   /** default constructor. initializes to identity rotation (no rotation). */
+   AxisAngle() : 
+      VecBase<DATA_TYPE, 4>( (DATA_TYPE)0.0, (DATA_TYPE)1.0, 
+                             (DATA_TYPE)0.0, (DATA_TYPE)0.0 )
+   {
+   }
+   
+   /** copy constructor. */
+   AxisAngle( const AxisAngle& e ) : VecBase<DATA_TYPE, 4>( e )
+   {
+   }
+   
+   /** data constructor (angle/x,y,z).   angles are in radians. */
+   AxisAngle( const DATA_TYPE& rad_angle, const DATA_TYPE& x, 
+              const DATA_TYPE& y, const DATA_TYPE& z ) :
+            VecBase<DATA_TYPE, 4>( rad_angle, x, y, z )
+   {
+   }
+   
+   /** data constructor (angle/Vec3).   angles are in radians. */
+   AxisAngle( const DATA_TYPE& rad_angle, const Vec<DATA_TYPE, 3>& axis ) :
+            VecBase<DATA_TYPE, 4>( rad_angle, axis[0], axis[1], axis[2] )
+   {
+   }
+   
+   /** set raw data.   angles are in radians. */
+   void set( const DATA_TYPE& rad_angle, const DATA_TYPE& x, 
+             const DATA_TYPE& y, const DATA_TYPE& z )
+   {
+      VecBase<DATA_TYPE, 4>::set( rad_angle, x, y, z );
+   }
+   
+   /** set data.   angles are in radians. */
+   void set( const DATA_TYPE& rad_angle, const Vec<DATA_TYPE, 3>& axis )
+   {
+      VecBase<DATA_TYPE, 4>::set( rad_angle, axis[0], axis[1], axis[2] );
+   }
+   
+   /** set the axis portion of the AxisAngle
+    *   @param axis     the desired 3D vector axis to rotate about
+    *   @post           the axis of the object is set
+    */
+   void setAxis( const Vec<DATA_TYPE, 3>& axis ) 
+   { 
+      VecBase<DATA_TYPE, 4>::operator[]( 1 ) = axis[0];
+      VecBase<DATA_TYPE, 4>::operator[]( 2 ) = axis[1];
+      VecBase<DATA_TYPE, 4>::operator[]( 3 ) = axis[2];
+   }
+   
+   /** set the angle (twist) part of the AxisAngle, as a radian value.
+    *  @param rad_angle    the desired twist angle, in radians
+    *  @post the angle of the object is set
+    */
+   void setAngle( const DATA_TYPE& rad_angle ) 
+   {
+      VecBase<DATA_TYPE, 4>::operator[]( 0 ) = rad_angle;
+   }
+   
+   /** get the axis portion of the AxisAngle
+    *  @return  a vector of the axis, which may or may not be normalized.
+    */
+   Vec<DATA_TYPE, 3> getAxis() const 
+   { 
+      return Vec<DATA_TYPE, 3>( VecBase<DATA_TYPE, 4>::operator[]( 1 ),
+                                VecBase<DATA_TYPE, 4>::operator[]( 2 ),
+                                VecBase<DATA_TYPE, 4>::operator[]( 3 ) );
+   }
+   
+   /** get the angle (twist) part of the AxisAngle.
+    *  @return the twist value in radians
+    */
+   const DATA_TYPE& getAngle() const 
+   {
+      return VecBase<DATA_TYPE, 4>::operator[]( 0 );
+   }
+};
+
+const AxisAngle<float> AXISANGLE_IDENTITYF( 0.0f, 1.0f, 0.0f, 0.0f );
+const AxisAngle<double> AXISANGLE_IDENTITYD( 0.0, 1.0, 0.0, 0.0 );
+
+typedef AxisAngle<float> AxisAnglef;
+typedef AxisAngle<double> AxisAngled;
+
+} // end of namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngleOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngleOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/AxisAngleOps.h	(revision 4)
@@ -0,0 +1,118 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          AxisAngleOps.h,v
+ * Date modified: 2004/05/25 16:36:28
+ * Version:       1.4
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum 
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+
+#ifndef _GMTL_AXIS_ANGLE_OPS_H_
+#define _GMTL_AXIS_ANGLE_OPS_H_
+
+#include <gmtl/AxisAngle.h>
+
+namespace gmtl
+{
+
+/** @ingroup Compare
+ *  @name AxisAngle Comparitors
+ *  @{
+ */
+
+/**
+ * Compares 2 AxisAngles to see if they are exactly the same.
+ *
+ * @param a1   the first AxisAngle
+ * @param a2   the second AxisAngle
+ *
+ * @return  true if a1 equals a2; false if they differ
+ */
+template<class DATA_TYPE>
+inline bool operator==(const AxisAngle<DATA_TYPE>& a1,
+                       const AxisAngle<DATA_TYPE>& a2)
+{
+   // @todo metaprogramming.
+   if (a1[0] != a2[0]) return false;
+   if (a1[1] != a2[1]) return false;
+   if (a1[2] != a2[2]) return false;
+   if (a1[3] != a2[3]) return false;
+   return true;
+}
+
+/**
+ * Compares 2 AxisAngles to see if they are NOT exactly the same.
+ *
+ * @param a1   the first AxisAngle
+ * @param a2   the second AxisAngle
+ *
+ * @return  true if a1 does not equal a2; false if they are equal
+ */
+template<class DATA_TYPE>
+inline bool operator!=(const AxisAngle<DATA_TYPE>& a1,
+                       const AxisAngle<DATA_TYPE>& a2)
+{
+   return !(a1 == a2);
+}
+
+/**
+ * Compares a1 and a2 to see if they are the same within the given epsilon
+ * tolerance.
+ *
+ * @pre eps must be >= 0
+ *
+ * @param a1   the first vector
+ * @param a2   the second vector
+ * @param eps  the epsilon tolerance value
+ *
+ * @return  true if a1 equals a2 within tolerance; false if they differ
+ */
+template<class DATA_TYPE>
+inline bool isEqual( const AxisAngle<DATA_TYPE>& a1,
+                     const AxisAngle<DATA_TYPE>& a2, 
+                     const DATA_TYPE eps = 0 )
+{
+   gmtlASSERT( eps >= (DATA_TYPE)0 );
+   
+   // @todo metaprogramming.
+   if (!Math::isEqual( a1[0], a2[0], eps )) return false;
+   if (!Math::isEqual( a1[1], a2[1], eps )) return false;
+   if (!Math::isEqual( a1[2], a2[2], eps )) return false;
+   if (!Math::isEqual( a1[3], a2[3], eps )) return false;
+   return true;
+}
+
+// @todo write isEquiv function for AxisAngle
+
+
+/** @} */
+
+} // namespace
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Comparitors.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Comparitors.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Comparitors.h	(revision 4)
@@ -0,0 +1,71 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Comparitors.h,v
+ * Date modified: 2002/01/26 23:47:53
+ * Version:       1.2
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum 
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_COMPARITORS_H_
+#define _GMTL_COMPARITORS_H_
+
+// This file contains helper comparitors
+//
+// They can be used as comparison functors for STL container
+// operations (or for anything else you may want to use them for...)
+//
+
+#include <gmtl/Vec3.h>
+#include <gmtl/Point3.h>
+
+namespace gmtl
+{
+   // Allows for the comparison of projected point distances
+   // onto a given vector
+   struct CompareIndexPointProjections
+   {
+   public:
+      CompareIndexPointProjections() : points(NULL)
+      {;}
+
+      bool operator()(const unsigned x, const unsigned y)
+      {
+         float xVal = sortDir.dot((*points)[x]);
+         float yVal = sortDir.dot((*points)[y]);
+
+         return (xVal < yVal);
+      }
+
+      const std::vector<Point3>* points;
+      gmtl::Vec3                 sortDir;       // Direction to sort by
+   };
+};
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Config.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Config.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Config.h	(revision 4)
@@ -0,0 +1,48 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Config.h,v
+ * Date modified: 2004/11/25 15:45:16
+ * Version:       1.3
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_CONFIG_H_
+#define _GMTL_CONFIG_H_
+
+// Configuration parameters for GMTL
+
+/** If defined, constructors increment counter
+ * that tracks how many objects have been created.
+ */
+//#define GMTL_COUNT_CONSTRUCT_CALLS 1
+
+
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Containment.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Containment.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Containment.h	(revision 4)
@@ -0,0 +1,708 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Containment.h,v
+ * Date modified: 2005/05/16 14:19:44
+ * Version:       1.17
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_CONTAINMENT_H_
+#define _GMTL_CONTAINMENT_H_
+
+// new stuff
+#include <vector>
+#include <gmtl/Sphere.h>
+#include <gmtl/AABox.h>
+#include <gmtl/VecOps.h>
+
+// old stuff
+//#include <gmtl/OOBox.h>
+//#include <gmtl/AABox.h>
+//#include <gmtl/Fit/GaussPointsFit.h>
+//#include <gmtl/matVecFuncs.h>
+//#include <gmtl/Quat.h>
+
+namespace gmtl
+{
+
+//-----------------------------------------------------------------------------
+// Sphere
+//-----------------------------------------------------------------------------
+
+/**
+ * Tests if the given point is inside or on the surface of the given spherical
+ * volume.
+ *
+ * @param container  the sphere to test against
+ * @param pt         the point to test with
+ *
+ * @return  true if pt is inside container, false otherwise
+ */
+template< class DATA_TYPE >
+bool isInVolume( const Sphere<DATA_TYPE>& container,
+                 const Point<DATA_TYPE, 3>& pt )
+{
+   // The point is inside the sphere if the vector computed from the center of
+   // the sphere to the point has a magnitude less than or equal to the radius
+   // of the sphere.
+   // |pt - center| <= radius
+   return ( length(gmtl::Vec<DATA_TYPE,3>(pt - container.mCenter)) <= container.mRadius );
+}
+
+/**
+ * Tests if the given sphere is completely inside or on the surface of the given
+ * spherical volume.
+ *
+ * @param container  the sphere acting as the container
+ * @param sphere     the sphere that may be inside container
+ *
+ * @return  true if sphere is inside container, false otherwise
+ */
+template< class DATA_TYPE >
+bool isInVolume( const Sphere<DATA_TYPE>& container,
+                 const Sphere<DATA_TYPE>& sphere )
+{
+   // the sphere is inside container if the distance between the centers of the
+   // spheres plus the radius of the inner sphere is less than or equal to the
+   // radius of the containing sphere.
+   // |sphere.center - container.center| + sphere.radius <= container.radius
+   return ( length(gmtl::Vec<DATA_TYPE,3>(sphere.mCenter - container.mCenter)) + sphere.mRadius
+            <= container.mRadius );
+}
+
+/**
+ * Modifies the existing sphere to tightly enclose itself and the given point.
+ *
+ * @param container  [in,out] the sphere that will be extended
+ * @param pt         [in]     the point which the sphere should contain
+ */
+template< class DATA_TYPE >
+void extendVolume( Sphere<DATA_TYPE>& container,
+                   const Point<DATA_TYPE, 3>& pt )
+{
+   // check if we already contain the point
+   if ( isInVolume( container, pt ) )
+   {
+      return;
+   }
+
+   // make a vector pointing from the center of the sphere to pt. this is the
+   // direction in which we need to move the sphere's center
+   Vec<DATA_TYPE, 3> dir = pt - container.mCenter;
+   DATA_TYPE len = normalize( dir );
+
+   // compute what the new radius should be
+   DATA_TYPE newRadius =  (len + container.mRadius) * DATA_TYPE(0.5);
+
+   // compute the new center for the sphere
+   Point<DATA_TYPE, 3> newCenter = container.mCenter +
+                                   (dir * (newRadius - container.mRadius));
+
+   // modify container to its new values
+   container.mCenter = newCenter;
+   container.mRadius = newRadius;
+}
+
+/**
+ * Modifies the container to tightly enclose itself and the given sphere.
+ *
+ * @param container  [in,out] the sphere that will be extended
+ * @param sphere     [in]     the sphere which container should contain
+ */
+template< class DATA_TYPE >
+void extendVolume( Sphere<DATA_TYPE>& container,
+                   const Sphere<DATA_TYPE>& sphere )
+{
+   // check if we already contain the sphere
+   if ( isInVolume( container, sphere ) )
+   {
+      return;
+   }
+
+   // make a vector pointing from the center of container to sphere. this is the
+   // direction in which we need to move container's center
+   Vec<DATA_TYPE, 3> dir = sphere.mCenter - container.mCenter;
+   DATA_TYPE len = normalize( dir );
+
+   // compute what the new radius should be
+   DATA_TYPE newRadius = (len + sphere.mRadius + container.mRadius) *
+                         DATA_TYPE(0.5);
+
+   // compute the new center for container
+   Point<DATA_TYPE, 3> newCenter = container.mCenter +
+                                   (dir * (newRadius - container.mRadius));
+
+   // modify container to its new values
+   container.mCenter = newCenter;
+   container.mRadius = newRadius;
+}
+
+/**
+ * Modifies the given sphere to tightly enclose all points in the given
+ * std::vector. This operation is O(n) and uses sqrt(..) liberally. :(
+ *
+ * @param container  [out]    the sphere that will be modified to tightly
+ *                            enclose all the points in pts
+ * @param pts        [in]     the list of points to contain
+ *
+ * @pre  pts must contain at least 2 points
+ */
+template< class DATA_TYPE >
+void makeVolume( Sphere<DATA_TYPE>& container,
+                 const std::vector< Point<DATA_TYPE, 3> >& pts )
+{
+   gmtlASSERT( pts.size() > 0  && "pts must contain at least 1 point" );
+
+   // Implementation based on the Sphere Centered at Average of Points algorithm
+   // found in "3D Game Engine Design" by Devud G, Eberly (pg. 27)
+   typename std::vector< Point<DATA_TYPE, 3> >::const_iterator itr = pts.begin();
+
+   // compute the average of the points as the center
+   Point<DATA_TYPE, 3> sum = *itr;
+   ++itr;
+   while ( itr != pts.end() )
+   {
+      sum += *itr;
+      ++itr;
+   }
+   container.mCenter = sum / DATA_TYPE(pts.size());
+
+   // compute the distance from the computed center to point furthest from that
+   // center as the radius
+   DATA_TYPE radiusSqr(0);
+   for ( itr = pts.begin(); itr != pts.end(); ++itr )
+   {
+      DATA_TYPE len = lengthSquared( gmtl::Vec<DATA_TYPE,3>( (*itr) - container.mCenter) );
+      if ( len > radiusSqr )
+         radiusSqr = len;
+   }
+
+   container.mRadius = Math::sqrt( radiusSqr );
+}
+
+/*
+template< class DATA_TYPE >
+void makeVolume( Sphere<DATA_TYPE>& container,
+                 const std::vector< Point<DATA_TYPE, 3> >& pts )
+{
+   gmtlASSERT( pts.size() > 1  && "pts must contain at least 2 points" );
+
+   // make a sphere around the first 2 points and then extend the sphere by each
+   // point thereafter. we could probably be smarter about this ...
+   std::vector< Point<DATA_TYPE, 3> >::const_iterator itr = pts.begin();
+
+   // make the initial sphere
+   const Point<DATA_TYPE, 3>& first = *itr;
+   ++itr;
+   const Point<DATA_TYPE, 3>& second = *itr;
+   ++itr;
+   const Vec<DATA_TYPE, 3> dir = second - first;
+   container.mRadius = length(dir) * DATA_TYPE(0.5);
+   container.mCenter = first + (dir * container.mRadius);
+
+   // iterate through the remaining points and extend the container to fit each
+   // point. yay code reuse!
+   while ( itr != pts.end() )
+   {
+      extendVolume( container, *itr );
+      ++itr;
+   }
+}
+*/
+/**
+ * Modifies the given sphere to tightly enclose all spheres in the given
+ * std::vector. This operation is O(n) and uses sqrt(..) liberally. :(
+ *
+ * @param container  [out]    the sphere that will be modified to tightly
+ *                            enclose all the spheres in spheres
+ * @param spheres    [in]     the list of spheres to contain
+ *
+ * @pre  spheres must contain at least 2 points
+ */
+/*
+template< class DATA_TYPE >
+void makeVolume( Sphere<DATA_TYPE>& container,
+                 const std::vector< Sphere<DATA_TYPE> >& spheres )
+{
+   gmtlASSERT( spheres.size() > 1  && "spheres must contain at least 2 points" );
+
+   // make a sphere around the first 2 points and then extend the sphere by each
+   // point thereafter. we could probably be smarter about this ...
+   std::vector< Sphere<DATA_TYPE> >::const_iterator itr = spheres.begin();
+
+   // make the initial sphere
+   const Sphere<DATA_TYPE>& first = *itr;
+   ++itr;
+   const Sphere<DATA_TYPE>& second = *itr;
+   ++itr;
+   const Vec<DATA_TYPE, 3> dir = second.mCenter - first.mCenter;
+   container.mRadius = (length(dir) + first.mRadius + second.mRadius) *
+                       DATA_TYPE(0.5);
+   container.mCenter = first.mCenter +
+                       (dir * (container.mRadius - first.mRadius));
+
+   // iterate through the remaining points and extend the container to fit each
+   // point. yay code reuse!
+   while ( itr != spheres.end() )
+   {
+      extendVolume( container, *itr );
+      ++itr;
+   }
+}
+*/
+/**
+ * Tests if the given point is on the surface of the container with zero
+ * tolerance.
+ *
+ * @param container     the container to test against
+ * @param pt            the test point
+ *
+ * @return  true if pt is on the surface of container, false otherwise
+ */
+template< class DATA_TYPE >
+bool isOnVolume( const Sphere<DATA_TYPE>& container,
+                 const Point<DATA_TYPE, 3>& pt )
+{
+   // |center - pt| - radius == 0
+   return ( length(gmtl::Vec<DATA_TYPE,3>(container.mCenter - pt)) - container.mRadius == 0 );
+}
+
+/**
+ * Tests of the given point is on the surface of the container with the given
+ * tolerance.
+ *
+ * @param container     the container to test against
+ * @param pt            the test point
+ * @param tol           the epsilon tolerance
+ *
+ * @return  true if pt is on the surface of container, false otherwise
+ */
+template< class DATA_TYPE >
+bool isOnVolume( const Sphere<DATA_TYPE>& container,
+                 const Point<DATA_TYPE, 3>& pt,
+                 const DATA_TYPE& tol )
+{
+   gmtlASSERT( tol >= 0 && "tolerance must be positive" );
+
+   // abs( |center-pt| - radius ) < tol
+   return ( Math::abs( length( gmtl::Vec<DATA_TYPE,3>(container.mCenter - pt)) - container.mRadius )
+            <= tol );
+}
+
+//-----------------------------------------------------------------------------
+// AABox
+//-----------------------------------------------------------------------------
+
+/**
+ * Tests if the given point is inside (or on) the surface of the given AABox
+ * volume.
+ *
+ * @param container  the AABox to test against
+ * @param pt         the point to test with
+ *
+ * @return  true if pt is inside container, false otherwise
+ */
+template< class DATA_TYPE>
+bool isInVolume(const AABox<DATA_TYPE>& container,
+                const Point<DATA_TYPE, 3>& pt)
+{
+   if (! container.isEmpty())
+   {
+      return ( pt[0] >= container.mMin[0] &&
+               pt[1] >= container.mMin[1] &&
+               pt[2] >= container.mMin[2] &&
+               pt[0] <= container.mMax[0] &&
+               pt[1] <= container.mMax[1] &&
+               pt[2] <= container.mMax[2]);
+   }
+   else
+   {
+      return false;
+   }
+}
+
+/**
+ * Tests if the given point is inside (not on) the surface of the given AABox
+ * volume.  This method is "exclusive" because it does not consider the surface
+ * to be a part of the space.
+ *
+ * @param container  the AABox to test against
+ * @param pt         the point to test with
+ *
+ * @return  true if pt is inside container (but not on surface), false otherwise
+ */
+template< class DATA_TYPE>
+bool isInVolumeExclusive(const AABox<DATA_TYPE>& container,
+                const Point<DATA_TYPE, 3>& pt)
+{
+   if (! container.isEmpty())
+   {
+      return ( pt[0] > container.mMin[0] &&
+               pt[1] > container.mMin[1] &&
+               pt[2] > container.mMin[2] &&
+               pt[0] < container.mMax[0] &&
+               pt[1] < container.mMax[1] &&
+               pt[2] < container.mMax[2]);
+   }
+   else
+   {
+      return false;
+   }
+}
+
+
+
+
+/**
+ * Tests if the given AABox is completely inside or on the surface of the given
+ * AABox container.
+ *
+ * @param container  the AABox acting as the container
+ * @param box        the AABox that may be inside container
+ *
+ * @return  true if AABox is inside container, false otherwise
+ */
+template< class DATA_TYPE >
+bool isInVolume(const AABox<DATA_TYPE>& container,
+                const AABox<DATA_TYPE>& box)
+{
+   // Empty boxes don't overlap
+   if (container.isEmpty() || box.isEmpty())
+   {
+      return false;
+   }
+
+   // Test that the boxes are not overlapping on any axis
+   if (container.mMax[0] < box.mMin[0] || container.mMin[0] > box.mMax[0] ||
+       container.mMax[1] < box.mMin[1] || container.mMin[1] > box.mMax[1] ||
+       container.mMax[2] < box.mMin[2] || container.mMin[2] > box.mMax[2])
+   {
+      return false;
+   }
+   else
+   {
+      return true;
+   }
+}
+
+/**
+ * Modifies the existing AABox to tightly enclose itself and the given point.
+ *
+ * @param container  [in,out] the AABox that will be extended
+ * @param pt         [in]     the point which the AABox should contain
+ */
+template< class DATA_TYPE >
+void extendVolume(AABox<DATA_TYPE>& container,
+                  const Point<DATA_TYPE, 3>& pt)
+{
+   if (! container.isEmpty())
+   {
+      // X coord
+      if (pt[0] > container.mMax[0])
+      {
+         container.mMax[0] = pt[0];
+      }
+      else if (pt[0] < container.mMin[0])
+      {
+         container.mMin[0] = pt[0];
+      }
+
+      // Y coord
+      if (pt[1] > container.mMax[1])
+      {
+         container.mMax[1] = pt[1];
+      }
+      else if (pt[1] < container.mMin[1])
+      {
+         container.mMin[1] = pt[1];
+      }
+
+      // Z coord
+      if (pt[2] > container.mMax[2])
+      {
+         container.mMax[2] = pt[2];
+      }
+      else if (pt[2] < container.mMin[2])
+      {
+         container.mMin[2] = pt[2];
+      }
+   }
+   else
+   {
+      // Make a box with essentially zero volume at the point
+      container.setMin(pt);
+      container.setMax(pt);
+      container.setEmpty(false);
+   }
+}
+
+/**
+ * Modifies the container to tightly enclose itself and the given AABox.
+ *
+ * @param container  [in,out] the AABox that will be extended
+ * @param box        [in]     the AABox which container should contain
+ */
+template< class DATA_TYPE >
+void extendVolume(AABox<DATA_TYPE>& container,
+                  const AABox<DATA_TYPE>& box)
+{
+   // Can't extend by an empty box
+   if (box.isEmpty())
+   {
+      return;
+   }
+
+   // An empty container is extended to be the box
+   if (container.isEmpty())
+   {
+      container = box;
+   }
+
+   // Just extend by the corners of the box
+   extendVolume(container, box.getMin());
+   extendVolume(container, box.getMax());
+}
+
+/**
+ * Creates an AABox that tightly encloses the given Sphere.
+ *
+ * @param box     set to the box
+ */
+template< class DATA_TYPE >
+void makeVolume(AABox<DATA_TYPE>& box, const Sphere<DATA_TYPE>& sph)
+{
+   const gmtl::Point<DATA_TYPE, 3>& center = sph.getCenter();
+   const DATA_TYPE& radius = sph.getRadius();
+
+   // Calculate the min and max points for the box
+   gmtl::Point<DATA_TYPE, 3> min_pt(center[0] - radius,
+                                    center[1] - radius,
+                                    center[2] - radius);
+   gmtl::Point<DATA_TYPE, 3> max_pt(center[0] + radius,
+                                    center[1] + radius,
+                                    center[2] + radius);
+
+   box.setMin(min_pt);
+   box.setMax(max_pt);
+   box.setEmpty(radius == DATA_TYPE(0));
+}
+
+/*
+//------------------------------------------------------------------------------
+// Begin old GMTL code
+//------------------------------------------------------------------------------
+inline void computeContainment( AABox& box, const std::vector<gmtl::Point3>& points,
+                         Point3& minPt, Point3& maxPt )
+//void MgcContAlignedBox (int iQuantity, const MgcVector3* akPoint,
+//    MgcVector3& rkMin, MgcVector3& rkMax)
+{
+   if (points.empty())
+      return;
+
+   minPt = points[0];
+   maxPt = minPt;
+
+   for (unsigned i = 1; i < points.size(); i++)
+   {
+      if ( points[i][Xelt] < minPt[Xelt] )
+         minPt[Xelt] = points[i][Xelt];
+      else if ( points[i][Xelt] > maxPt[Xelt] )
+         maxPt[Xelt] = points[i][Xelt];
+
+      if ( points[i][Yelt] < minPt[Yelt] )
+         minPt[Yelt] = points[i][Yelt];
+      else if ( points[i][Yelt] > maxPt[Yelt] )
+         maxPt[Yelt] = points[i][Yelt];
+
+      if ( points[i][Zelt] < minPt[Zelt] )
+         minPt[Zelt] = points[i][Zelt];
+      else if ( points[i][Zelt] > maxPt[Zelt] )
+         maxPt[Zelt] = points[i][Zelt];
+   }
+
+   // Now update the box
+   box.makeEmpty();
+   box.mMax = maxPt;
+   box.mMin = minPt;
+}
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+//MgcBox3 MgcContOrientedBox (int iQuantity, const MgcVector3* akPoint)
+inline void computeContainment( OOBox& box, const std::vector<gmtl::Point3>& points)
+{
+    //MgcGaussPointsFit(iQuantity,akPoint,kBox.Center(),kBox.Axes(),
+    //    kBox.Extents());
+
+    gmtl::GaussPointsFit(points.size(), &points[0], box.center(), box.axes(), box.halfLens());
+
+    // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
+    // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
+    // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
+    // and max(y2).  The box center is then adjusted to be
+    //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
+    //        0.5*(min(y2)+max(y2))*U2
+#ifdef _DEBUG
+   gmtl::OOBox box_test;
+   box_test = box;
+   gmtl::Vec3 ax0 = box_test.axis(0);
+   gmtl::Vec3 ax1 = box_test.axis(1);
+   gmtl::Vec3 ax2 = box_test.axis(2);
+#endif
+
+    gmtlASSERT(box.axis(0).isNormalized());
+    gmtlASSERT(box.axis(1).isNormalized());
+    gmtlASSERT(box.axis(2).isNormalized());
+
+    // XXX: Sign is sometimes wrong here
+    // This is hack code to make it "work right"
+    Vec3 cross;
+    cross = box.axis(0).cross(box.axis(1));
+    cross.normalize();
+    box.axis(2) = cross;
+
+    Vec3 kDiff = points[0] - box.center();
+    float fY0Min = kDiff.dot(box.axis(0)), fY0Max = fY0Min;
+    float fY1Min = kDiff.dot(box.axis(1)), fY1Max = fY1Min;
+    float fY2Min = kDiff.dot(box.axis(2)), fY2Max = fY2Min;
+
+    float fY0, fY1, fY2;
+
+    for (unsigned i = 1; i < points.size(); i++)
+    {
+        kDiff = points[i] - box.center();
+
+        fY0 = kDiff.dot(box.axis(0));
+        if ( fY0 < fY0Min )
+            fY0Min = fY0;
+        else if ( fY0 > fY0Max )
+            fY0Max = fY0;
+
+        fY1 = kDiff.dot(box.axis(1));
+        if ( fY1 < fY1Min )
+            fY1Min = fY1;
+        else if ( fY1 > fY1Max )
+            fY1Max = fY1;
+
+        fY2 = kDiff.dot(box.axis(2));
+        if ( fY2 < fY2Min )
+            fY2Min = fY2;
+        else if ( fY2 > fY2Max )
+            fY2Max = fY2;
+    }
+
+    box.center() += (0.5*(fY0Min+fY0Max))*box.axis(0) +
+                    (0.5*(fY1Min+fY1Max))*box.axis(1) +
+                    (0.5*(fY2Min+fY2Max))*box.axis(2);
+
+    box.halfLen(0) = 0.5*(fY0Max - fY0Min);
+    box.halfLen(1) = 0.5*(fY1Max - fY1Min);
+    box.halfLen(2) = 0.5*(fY2Max - fY2Min);
+}
+
+*/
+/*
+inline void computeContainment (OOBox& out_box, const OOBox& box0, const OOBox& box1, bool fast=true)
+{
+   gmtl::OOBox ret_box;    // The resulting box
+
+   if (fast)
+   {
+      ret_box.center() = 0.5*(box0.center() + box1.center());       // Center at average
+
+      // Average the quats to get a new orientation
+      Quat quat0, quat1;
+      quat0.makeAxes(box0.axis(0), box0.axis(1), box0.axis(2));
+      quat1.makeAxes(box1.axis(0), box1.axis(1), box1.axis(2));
+      if ( quat0.dot(quat1) < 0.0 )
+         quat1 = -quat1;
+
+      Quat full_quat = quat0 + quat1;
+
+      //float inv_len = 1.0/Math::sqrt(full_quat.norm());
+      //full_quat = inv_len*full_quat;
+      full_quat.normalize();
+      full_quat.getAxes(ret_box.axis(0), ret_box.axis(1), ret_box.axis(2));
+
+      // Now that we have new orientation, extend half lens to cover the volume
+      //
+      unsigned i, j;
+      Point3 verts[8];
+      Vec3 diff;
+      float aDot;
+
+      ret_box.halfLen(0) = 0.0;
+      ret_box.halfLen(1) = 0.0;
+      ret_box.halfLen(2) = 0.0;
+
+      box0.getVerts(verts);
+      for (i = 0; i < 8; i++)
+      {
+         diff = verts[i] - ret_box.center();
+         for (j = 0; j < 3; j++)                       // For each axis of box0
+         {
+            aDot = Math::abs(diff.dot(ret_box.axis(j)));
+            if ( aDot > ret_box.halfLen(j) )
+               ret_box.halfLen(j) = aDot;
+         }
+      }
+
+      box1.getVerts(verts);
+      for (i = 0; i < 8; i++)
+      {
+         diff = verts[i] - ret_box.center();
+         for (j = 0; j < 3; j++)
+         {
+            aDot = Math::abs(diff.dot(ret_box.axis(j)));
+            if ( aDot > ret_box.halfLen(j) )
+               ret_box.halfLen(j) = aDot;
+         }
+      }
+   }
+   else     // Tighter fit
+   {
+      // Hack that will do it correctly, but is slow
+      Point3 verts[8];
+      std::vector<gmtl::Point3> vert_points;
+
+      box0.getVerts(verts);
+      for (unsigned i=0;i<8;i++) vert_points.push_back(verts[i]);
+      box1.getVerts(verts);
+      for (unsigned i=0;i<8;i++) vert_points.push_back(verts[i]);
+
+      computeContainment(ret_box, vert_points);
+   }
+
+   out_box = ret_box;
+}
+*/
+
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Coord.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Coord.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Coord.h	(revision 4)
@@ -0,0 +1,226 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Coord.h,v
+ * Date modified: 2004/11/12 01:34:48
+ * Version:       1.16
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum 
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_COORD_H_
+#define _GMTL_COORD_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Vec.h>
+#include <gmtl/AxisAngle.h>
+#include <gmtl/EulerAngle.h>
+#include <gmtl/Quat.h>
+#include <gmtl/Util/Meta.h>
+#include <gmtl/Util/StaticAssert.h>
+
+namespace gmtl
+{
+   
+/** coord is a position/rotation pair. 
+ *  coord consists of a position element and a rotation element.
+ *
+ * <h3> "How to define an Vector/Euler pair (32 bit float precision):" </h3>
+ * \code
+ *    Coord<Vec3f, EulerAngleXYZf> myEulerCoord;
+ * \endcode
+ *
+ * <h3> "Or use the built in typedefs:" </h3>
+ * \code
+ *    CoordVec3fEulerAngleXYZf myEulerCoord;
+ *    Coord3fQuat myOtherEulerCoord;
+ * \endcode
+ * @see Vec, AxisAngle, EulerAngle 
+ * @ingroup Types
+ */
+template <typename POS_TYPE, typename ROT_TYPE>
+class Coord
+{
+public:
+   Coord() : mPos(), mRot()
+   {
+   }
+   
+   typedef typename POS_TYPE::DataType DataType;
+   typedef POS_TYPE PosDataType;
+   typedef ROT_TYPE RotDataType;
+   enum Params
+   {
+       PosSize = POS_TYPE::Size,
+       RotSize = ROT_TYPE::Size
+   };
+    
+   Coord( const Coord<POS_TYPE, ROT_TYPE>& coord ) : mPos( coord.mPos ), mRot( coord.mRot )
+   {
+   }
+   
+   Coord( const POS_TYPE& pos, const ROT_TYPE& rot ) : mPos( pos ), mRot( rot )
+   {
+   }
+
+   /** @name Multi-arg Constructors 
+   *  Construct objects from primitive types
+   *  Just assigns values in order to the pos and rot members' members.
+   */
+   //@{
+   Coord( DataType a0, DataType a1, DataType a2, DataType a3, DataType a4, DataType a5 )
+   {
+      GMTL_STATIC_ASSERT(PosSize == 3, Using_incorrect_number_of_args_for_type_size);
+      GMTL_STATIC_ASSERT(RotSize == 3, Using_incorrect_number_of_args_for_type_size);
+      if(PosSize == 3)
+      {
+         mPos[0] = a0; mPos[1] = a1; mPos[2] = a2;
+         mRot[0] = a3; mRot[1] = a4; mRot[2] = a5; 
+      }
+      else
+      {
+         gmtlASSERT(false && "Constructor not supported for pos size");
+      }
+   }
+
+   Coord( DataType a0, DataType a1, DataType a2, DataType a3, DataType a4, DataType a5, DataType a6 )
+   {
+      GMTL_STATIC_ASSERT( (PosSize == 3 && RotSize == 4) || (PosSize == 4 && RotSize == 3), Using_incorrect_number_of_args_for_type_size);
+      if(PosSize == 3)
+      {
+         mPos[0] = a0; mPos[1] = a1; mPos[2] = a2;
+         mRot[0] = a3; mRot[1] = a4; mRot[2] = a5; mRot[3] = a6; 
+      }
+      else if(PosSize == 4)
+      {
+         mPos[0] = a0; mPos[1] = a1; mPos[2] = a2; mPos[3] = a3;
+         mRot[0] = a4; mRot[1] = a5; mRot[2] = a6; 
+      }
+      else
+      {
+         gmtlASSERT(false && "Constructor not supported for pos size");
+      }
+
+   }
+  
+   Coord( DataType a0, DataType a1, DataType a2, DataType a3, DataType a4, DataType a5, DataType a6, DataType a7 )
+   {
+      GMTL_STATIC_ASSERT(PosSize == 4, Using_incorrect_number_of_args_for_type_size);
+      GMTL_STATIC_ASSERT(RotSize == 4, Using_incorrect_number_of_args_for_type_size);
+      if(PosSize == 4)
+      {
+         mPos[0] = a0; mPos[1] = a1; mPos[2] = a2; mPos[3] = a3;
+         mRot[0] = a4; mRot[1] = a5; mRot[2] = a6; mRot[3] = a7;   
+      }
+      else
+      {
+         gmtlASSERT(false && "Constructor not supported for pos size");
+      }
+   }
+   //@}
+
+   const POS_TYPE& getPos() const { return mPos; }
+   const ROT_TYPE& getRot() const { return mRot; }
+   
+   /// @todo what about having a pos, and a const_pos naming convention?
+   /// @todo what about having a rot, and a const_rot naming convention?
+   
+   /** accessor to the position element */
+   POS_TYPE& pos() { return mPos; }
+
+   /** accessor to the rotation element */
+   ROT_TYPE& rot() { return mRot; }
+   
+   /** const accessor to the position element */
+   //const POS_TYPE& pos() const { return mPos; }
+
+   /** const accessor to the rotation element */
+   //const ROT_TYPE& rot() const  { return mRot; }
+
+public:
+   POS_TYPE mPos;
+   ROT_TYPE mRot;
+};
+
+typedef Coord<Vec3d, EulerAngleXYZd> CoordVec3EulerAngleXYZd;
+typedef Coord<Vec3f, EulerAngleXYZf> CoordVec3EulerAngleXYZf;
+typedef Coord<Vec4d, EulerAngleXYZd> CoordVec4EulerAngleXYZd;
+typedef Coord<Vec4f, EulerAngleXYZf> CoordVec4EulerAngleXYZf;
+
+typedef Coord<Vec3d, EulerAngleZYXd> CoordVec3EulerAngleZYXd;
+typedef Coord<Vec3f, EulerAngleZYXf> CoordVec3EulerAngleZYXf;
+typedef Coord<Vec4d, EulerAngleZYXd> CoordVec4EulerAngleZYXd;
+typedef Coord<Vec4f, EulerAngleZYXf> CoordVec4EulerAngleZYXf;
+
+typedef Coord<Vec3d, EulerAngleZXYd> CoordVec3EulerAngleZXYd;
+typedef Coord<Vec3f, EulerAngleZXYf> CoordVec3EulerAngleZXYf;
+typedef Coord<Vec4d, EulerAngleZXYd> CoordVec4EulerAngleZXYd;
+typedef Coord<Vec4f, EulerAngleZXYf> CoordVec4EulerAngleZXYf;
+
+typedef Coord<Vec3d, AxisAngled> CoordVec3AxisAngled;
+typedef Coord<Vec3f, AxisAnglef> CoordVec3AxisAnglef;
+typedef Coord<Vec4d, AxisAngled> CoordVec4AxisAngled;
+typedef Coord<Vec4f, AxisAnglef> CoordVec4AxisAnglef;
+
+
+
+/** 3 elt types */
+typedef Coord<Vec3f, EulerAngleXYZf> Coord3fXYZ;
+typedef Coord<Vec3f, EulerAngleZYXf> Coord3fZYX;
+typedef Coord<Vec3f, EulerAngleZXYf> Coord3fZXY;
+typedef Coord<Vec3d, EulerAngleXYZd> Coord3dXYZ;
+typedef Coord<Vec3d, EulerAngleZYXd> Coord3dZYX;
+typedef Coord<Vec3d, EulerAngleZXYd> Coord3dZXY;
+
+/** 4 elt types */
+typedef Coord<Vec4f, EulerAngleXYZf> Coord4fXYZ;
+typedef Coord<Vec4f, EulerAngleZYXf> Coord4fZYX;
+typedef Coord<Vec4f, EulerAngleZXYf> Coord4fZXY;
+typedef Coord<Vec4d, EulerAngleXYZd> Coord4dXYZ;
+typedef Coord<Vec4d, EulerAngleZYXd> Coord4dZYX;
+typedef Coord<Vec4d, EulerAngleZXYd> Coord4dZXY;
+
+/** 3 elt types */
+typedef Coord<Vec3f, Quatf> Coord3fQuat;
+typedef Coord<Vec3d, Quatd> Coord3dQuat;
+
+/** 4 elt types */
+typedef Coord<Vec4f, Quatf> Coord4fQuat;
+typedef Coord<Vec4d, Quatd> Coord4dQuat;
+
+
+/** 3 elt types */
+typedef Coord<Vec3f, AxisAnglef> Coord3fAxisAngle;
+typedef Coord<Vec3d, AxisAngled> Coord3dAxisAngle;
+
+/** 4 elt types */
+typedef Coord<Vec4f, AxisAnglef> Coord4fAxisAngle;
+typedef Coord<Vec4d, AxisAngled> Coord4dAxisAngle;
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/CoordOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/CoordOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/CoordOps.h	(revision 4)
@@ -0,0 +1,90 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          CoordOps.h,v
+ * Date modified: 2004/05/25 16:36:28
+ * Version:       1.6
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_COORD_OPS_H_
+#define _GMTL_COORD_OPS_H_
+
+#include <gmtl/Coord.h>
+
+namespace gmtl
+{
+/** @ingroup Compare Coord 
+ * @name Coord Comparitors
+ * @{
+ */
+
+   /** Compare two coordinate frames for equality.
+    * @param c1   the first Coord
+    * @param c2   the second Coord
+    * @return     true if c1 is the same as c2, false otherwise
+    */
+   template <typename POS_TYPE, typename ROT_TYPE>
+   inline bool operator==( const Coord<POS_TYPE, ROT_TYPE>& c1, 
+                           const Coord<POS_TYPE, ROT_TYPE>& c2 )
+   {
+      return bool( c1.getPos() == c2.getPos() &&
+                   c1.getRot() == c2.getRot() );
+   }
+
+   /** Compare two coordinate frames for not-equality.
+    * @param c1   the first Coord
+    * @param c2   the second Coord
+    * @return     true if c1 is different from c2, false otherwise
+    */
+   template <typename POS_TYPE, typename ROT_TYPE>
+   inline bool operator!=( const Coord<POS_TYPE, ROT_TYPE>& c1, 
+                           const Coord<POS_TYPE, ROT_TYPE>& c2 )
+   {
+      return !operator==( c1, c2 );
+   }
+
+   /** Compare two coordinate frames for equality with a given tolerance.
+    * @param c1   the first Coord
+    * @param c2   the second Coord
+    * @param tol  the tolerance coordinate frame of the same type as c1 and c2
+    * @return     true if c1 is equal within a tolerance of c2, false otherwise
+    */
+   template <typename POS_TYPE, typename ROT_TYPE>
+   inline bool isEqual( const Coord<POS_TYPE, ROT_TYPE>& c1, 
+                        const Coord<POS_TYPE, ROT_TYPE>& c2, 
+                        typename Coord<POS_TYPE, ROT_TYPE>::DataType tol = 0 )
+   {
+      return bool( isEqual( c1.getPos(), c2.getPos(), tol ) &&
+                   isEqual( c1.getRot(), c2.getRot(), tol )     );
+   }
+/** @} */
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Defines.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Defines.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Defines.h	(revision 4)
@@ -0,0 +1,104 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Defines.h,v
+ * Date modified: 2004/10/30 18:24:32
+ * Version:       1.9
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_DEFINES_H
+#define _GMTL_DEFINES_H
+
+namespace gmtl
+{
+   /** use the values in this enum to index vector data 
+    *  types (such as Vec, Point, Quat).
+    *
+    * <h3> "Example (access elements in a Vec3f):" </h3>
+    * \code
+    *    Vec3f vec;
+    *    vec[Xelt] = 1.0f;
+    *    vec[Yelt] = 3.0f;
+    *    vec[Zelt] = 2.0f;
+    * \endcode
+    * @ingroup Defines
+    */
+   enum VectorIndex { Xelt = 0, Yelt = 1, Zelt = 2, Welt = 3 };
+
+   /**
+    * Used to describe where a point lies in relationship to a plane.
+    * ON_PLANE means the point lies on the plane.
+    * POS_SIDE means the point lies on the same side as the surface normal.
+    * NEG_SIDE means the point lies on the opposite side as the ssurface normal.
+    * @ingroup Defines
+    */
+   enum PlaneSide
+   {
+      ON_PLANE,
+      POS_SIDE,
+      NEG_SIDE
+   };
+
+   /** @ingroup Defines
+    * @name Constants
+    * @{
+    */    
+   const float GMTL_EPSILON = 1.0e-6f;
+   const float GMTL_MAT_EQUAL_EPSILON = 0.001f;  // Epsilon for matrices to be equal
+   const float GMTL_VEC_EQUAL_EPSILON = 0.0001f; // Epsilon for vectors to be equal
+   /** @} */
+   
+#define GMTL_NEAR(x,y,eps) (gmtl::Math::abs((x)-(y))<(eps))
+
+};
+
+// Platform-specific settings.
+#if defined(__sun) || defined(__APPLE__) || defined(__hpux) ||  \
+    defined(_XOPEN_SOURCE)
+#define NO_ACOSF 1
+#define NO_ASINF 1
+#define NO_TANF 1
+#define NO_ATAN2F 1
+#define NO_COSF 1
+#define NO_SINF 1
+#define NO_TANF 1
+#define NO_SQRTF 1
+#define NO_LOGF 1
+#define NO_EXPF 1
+#define NO_POWF 1
+#define NO_CEILF 1
+#define NO_FLOORF 1
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1310
+#define GMTL_NO_METAPROG
+#endif
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngle.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngle.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngle.h	(revision 4)
@@ -0,0 +1,160 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          EulerAngle.h,v
+ * Date modified: 2003/04/01 13:21:47
+ * Version:       1.11
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_EULERANGLE_H_
+#define _GMTL_EULERANGLE_H_
+
+#include <gmtl/Math.h>     // for rotation order
+ 
+namespace gmtl
+{
+
+/** EulerAngle: Represents a group of euler angles.
+ *  Euler angle can be used to represent rotations in 3-space.
+ *
+ *  To some people this rotation format can be more intuitive to specify than
+ *  Matrix, Quat, or AxisAngle formatted rotation.
+ *
+ *  For efficiency and to minimize problems from gimbal-lock, you should use
+ *  one of the other rotation formats instead (Quat or Matrix are preferred).
+ *
+ *  The internal data format is an array of 3 DATA_TYPE angle values, 
+ *  plus a RotationOrder that specifies how to build a rotation transform
+ *  from the 3 angle value.
+ *
+ *  IMPORTANT:
+ *  The 3 angles are in the order set ::getOrder(), not XYZ.
+ *  The values do not swap when order is changed after setting the angles.
+ *
+ * @pre all angles are in radians.
+ *
+ * @see EulerAnglef, EulerAngled
+ * @see Matrix, Quat, AxisAngle
+ * @ingroup Types
+ */
+template <typename DATA_TYPE, typename ROTATION_ORDER>
+class EulerAngle
+{
+public:
+   /// Use this to declare single value types of the same type as this object.
+   typedef DATA_TYPE DataType;
+
+   enum Params { Size = 3, Order = ROTATION_ORDER::ID };
+
+   /** default constructor. initializes to identity rotation (no rotation). */
+   EulerAngle()
+   {
+      gmtlASSERT( ROTATION_ORDER::IS_ROTORDER == 1 && 
+            "you must specify a RotationOrder derived type for the rotationorder in euler angle." );
+      mData[0] = DATA_TYPE( 0 );
+      mData[1] = DATA_TYPE( 0 );
+      mData[2] = DATA_TYPE( 0 );
+   }
+
+   /** copy constructor. */
+   EulerAngle( const EulerAngle& e )
+   {
+      mData[0] = e.mData[0];
+      mData[1] = e.mData[1];
+      mData[2] = e.mData[2];
+   }
+
+   /** data constructor.   angles are in radians. */
+   EulerAngle( DATA_TYPE p0, DATA_TYPE p1, DATA_TYPE p2 )
+   {
+      mData[0] = p0;
+      mData[1] = p1;
+      mData[2] = p2;
+   }
+   
+   /** set data.   angles are in radians. */
+   void set( const DATA_TYPE& p0, const DATA_TYPE& p1, 
+             const DATA_TYPE& p2 )
+   {
+      mData[0] = p0;
+      mData[1] = p1;
+      mData[2] = p2;
+   }
+   
+   //@{
+   /** Gets the ith component in this EulerAngle.
+    *  @param i    the zero-based index of the component to access.
+    *  @pre 0 <= i < 3
+    *  @return  a reference to the ith component
+    */
+   inline DATA_TYPE& operator[]( const unsigned i )
+   {
+      gmtlASSERT( i < Size );
+      return mData[i];
+   }
+   inline const DATA_TYPE&  operator[]( const unsigned i ) const
+   {
+      gmtlASSERT( i < Size );
+      return mData[i];
+   }
+   //@}
+   
+   //@{
+   /** Gets the internal array of the components.
+    *  @return  a pointer to the component array with length SIZE
+    */
+   DATA_TYPE* getData() { return mData; }
+   
+   /** Gets the internal array of the components (const version)
+    *  @return  a pointer to the component array with length SIZE
+    */
+   const DATA_TYPE* getData() const { return mData; }
+   //@}
+   
+private:
+   DATA_TYPE mData[Size];
+};
+
+const EulerAngle<float, XYZ> EULERANGLE_IDENTITY_XYZF( 0.0f, 0.0f, 0.0f );
+const EulerAngle<double, XYZ> EULERANGLE_IDENTITY_XYZD( 0.0, 0.0, 0.0 );
+const EulerAngle<float, ZYX> EULERANGLE_IDENTITY_ZYXF( 0.0f, 0.0f, 0.0f );
+const EulerAngle<double, ZYX> EULERANGLE_IDENTITY_ZYXD( 0.0, 0.0, 0.0 );
+const EulerAngle<float, ZXY> EULERANGLE_IDENTITY_ZXYF( 0.0f, 0.0f, 0.0f );
+const EulerAngle<double, ZXY> EULERANGLE_IDENTITY_ZXYD( 0.0, 0.0, 0.0 );
+
+typedef EulerAngle<float, XYZ> EulerAngleXYZf;
+typedef EulerAngle<double, XYZ> EulerAngleXYZd;
+typedef EulerAngle<float, ZYX> EulerAngleZYXf;
+typedef EulerAngle<double, ZYX> EulerAngleZYXd;
+typedef EulerAngle<float, ZXY> EulerAngleZXYf;
+typedef EulerAngle<double, ZXY> EulerAngleZXYd;
+
+} // end of namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngleOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngleOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/EulerAngleOps.h	(revision 4)
@@ -0,0 +1,115 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          EulerAngleOps.h,v
+ * Date modified: 2004/05/25 16:36:28
+ * Version:       1.5
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum 
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_EULER_ANGLE_OPS_H_
+#define _GMTL_EULER_ANGLE_OPS_H_
+
+#include <gmtl/EulerAngle.h>
+
+namespace gmtl
+{
+
+/** @ingroup Compare
+ *  @name EulerAngle Comparitors
+ *  @{
+ */
+
+/**
+ * Compares 2 EulerAngles (component-wise) to see if they are exactly the same.
+ *
+ * @param e1   the first EulerAngle
+ * @param e2   the second EulerAngle
+ *
+ * @return  true if e1 equals e2; false if they differ
+ */
+template<class DATA_TYPE, typename ROT_ORDER>
+inline bool operator==(const EulerAngle<DATA_TYPE, ROT_ORDER>& e1,
+                       const EulerAngle<DATA_TYPE, ROT_ORDER>& e2)
+{
+   // @todo metaprogramming.
+   if (e1[0] != e2[0]) return false;
+   if (e1[1] != e2[1]) return false;
+   if (e1[2] != e2[2]) return false;
+   return true;
+}
+
+/**
+ * Compares e1 and e2 (component-wise) to see if they are NOT exactly the same.
+ *
+ * @param e1   the first EulerAngle
+ * @param e2   the second EulerAngle
+ *
+ * @return  true if e1 does not equal e2; false if they are equal
+ */
+template<class DATA_TYPE, typename ROT_ORDER>
+inline bool operator!=(const EulerAngle<DATA_TYPE, ROT_ORDER>& e1,
+                       const EulerAngle<DATA_TYPE, ROT_ORDER>& e2)
+{
+   return(! (e1 == e2));
+}
+
+/**
+ * Compares e1 and e2 (component-wise) to see if they are the same within a
+ * given tolerance.
+ *
+ * @pre eps must be >= 0
+ *
+ * @param e1   the first EulerAngle
+ * @param e2   the second EulerAngle
+ * @param eps  the epsilon tolerance value, in radians
+ *
+ * @return  true if e1 is within the tolerance of e2; false if not
+ */
+template<class DATA_TYPE, typename ROT_ORDER>
+inline bool isEqual( const EulerAngle<DATA_TYPE, ROT_ORDER>& e1,
+                     const EulerAngle<DATA_TYPE, ROT_ORDER>& e2,
+                     const DATA_TYPE eps = 0 )
+{
+   gmtlASSERT(eps >= (DATA_TYPE)0);
+   
+   // @todo metaprogramming.
+   if (!Math::isEqual( e1[0], e2[0], eps )) return false;
+   if (!Math::isEqual( e1[1], e2[1], eps )) return false;
+   if (!Math::isEqual( e1[2], e2[2], eps )) return false;
+   return true;
+}
+
+// @todo write isEquiv function for EulerAngle
+
+
+/** @} */
+
+} // namespace
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/External/OpenSGConvert.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/External/OpenSGConvert.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/External/OpenSGConvert.h	(revision 4)
@@ -0,0 +1,43 @@
+#ifndef GMTL_OPENSG_CONVERT_H_
+#define GMTL_OPENSG_CONVERT_H_
+
+/** @file OpenSGConvert.h GMTL to OpenSG conversion functions
+* 
+* methods to convert between gtml and opensg matrix classes
+*/
+
+#include <gmtl/Matrix.h>
+#include <gmtl/Generate.h>
+#include <OpenSG/OSGMatrix.h>
+
+namespace gmtl
+{
+
+/** Convert an opensg matrix to a gmtl::Matrix
+ * @param mat        the matrix to write the OpenSG matrix data into
+ * @param osg_mat    the source OpenSG matrix
+ * @return     returns the equivalent GMTL matrix
+ */
+inline
+Matrix44f& set( Matrix44f& mat, const osg::Matrix& osg_mat )
+{
+   mat.set(osg_mat.getValues());
+   return mat;
+}
+
+/** Convert a GMTL matrix to a OpenSG matrix
+ * @param osg_mat     the matrix to write the GMTL matrix data into
+ * @param mat         the source GMTL matrix
+ * @return     returns the equivalent OpenSG matrix
+ */
+inline
+osg::Matrix& set(osg::Matrix& osg_mat, const Matrix44f& mat)
+{
+   osg_mat.setValue( mat.getData() );
+   return osg_mat;
+}
+
+}
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Fit/GaussPointsFit.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Fit/GaussPointsFit.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Fit/GaussPointsFit.h	(revision 4)
@@ -0,0 +1,319 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          GaussPointsFit.h,v
+ * Date modified: 2002/01/31 01:16:22
+ * Version:       1.3
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+// Based on code from:
+// Magic Software, Inc.
+// http://www.magic-software.com
+//
+#ifndef _GMTL_GAUSSPOINTSFIT_H
+#define _GMTL_GAUSSPOINTSFIT_H
+
+// Fit points with a Gaussian distribution.  The center is the mean of the
+// points, the axes are the eigenvectors of the covariance matrix, and the
+// extents are the eigenvalues of the covariance matrix and are returned in
+// increasing order.  The last two functions allow selection of valid
+// vertices from a pool.  The return value is 'true' if and only if at least
+// one vertex was valid.
+
+#include <gmtl/Vec3.h>
+#include <gmtl/Point3.h>
+#include <gmtl/Numerics/Eigen.h>
+
+namespace gmtl
+{
+
+/*
+void MgcGaussPointsFit (int iQuantity, const MgcVector2* akPoint,
+    MgcVector2& rkCenter, MgcVector2 akAxis[2], MgcReal afExtent[2]);
+*/
+
+void GaussPointsFit (int iQuantity, const Point3* akPoint,
+    Point3& rkCenter, Vec3 akAxis[3], float afExtent[3]);
+
+/*
+bool MgcGaussPointsFit (int iQuantity, const MgcVector2* akPoint,
+    const bool* abValid, MgcVector2& rkCenter, MgcVector2 akAxis[2],
+    MgcReal afExtent[2]);
+*/
+
+bool GaussPointsFit (int iQuantity, const Vec3* akPoint,
+    const bool* abValid, Vec3& rkCenter, Vec3 akAxis[3],
+    float afExtent[3]);
+	
+
+// --- Implementations ---- //
+void GaussPointsFit (int iQuantity, const Point3* akPoint,
+    Point3& rkCenter, Vec3 akAxis[3], float afExtent[3])
+{
+    // compute mean of points
+    rkCenter = akPoint[0];
+    unsigned i;
+    for (i = 1; i < iQuantity; i++)
+        rkCenter += akPoint[i];
+    float fInvQuantity = 1.0f/iQuantity;
+    rkCenter *= fInvQuantity;
+
+    // compute covariances of points
+    float fSumXX = 0.0, fSumXY = 0.0, fSumXZ = 0.0;
+    float fSumYY = 0.0, fSumYZ = 0.0, fSumZZ = 0.0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        Vec3 kDiff = akPoint[i] - rkCenter;
+        fSumXX += kDiff[Xelt]*kDiff[Xelt];
+        fSumXY += kDiff[Xelt]*kDiff[Yelt];
+        fSumXZ += kDiff[Xelt]*kDiff[Zelt];
+        fSumYY += kDiff[Yelt]*kDiff[Yelt];
+        fSumYZ += kDiff[Yelt]*kDiff[Zelt];
+        fSumZZ += kDiff[Zelt]*kDiff[Zelt];
+    }
+    fSumXX *= fInvQuantity;
+    fSumXY *= fInvQuantity;
+    fSumXZ *= fInvQuantity;
+    fSumYY *= fInvQuantity;
+    fSumYZ *= fInvQuantity;
+    fSumZZ *= fInvQuantity;
+
+    // compute eigenvectors for covariance matrix
+    gmtl::Eigen kES(3);
+    kES.Matrix(0,0) = fSumXX;
+    kES.Matrix(0,1) = fSumXY;
+    kES.Matrix(0,2) = fSumXZ;
+    kES.Matrix(1,0) = fSumXY;
+    kES.Matrix(1,1) = fSumYY;
+    kES.Matrix(1,2) = fSumYZ;
+    kES.Matrix(2,0) = fSumXZ;
+    kES.Matrix(2,1) = fSumYZ;
+    kES.Matrix(2,2) = fSumZZ;
+    kES.IncrSortEigenStuff3();
+
+    akAxis[0][Xelt] = kES.GetEigenvector(0,0);
+    akAxis[0][Yelt] = kES.GetEigenvector(1,0);
+    akAxis[0][Zelt] = kES.GetEigenvector(2,0);
+
+    akAxis[1][Xelt] = kES.GetEigenvector(0,1);
+    akAxis[1][Yelt] = kES.GetEigenvector(1,1);
+    akAxis[1][Zelt] = kES.GetEigenvector(2,1);
+
+    akAxis[2][Xelt] = kES.GetEigenvector(0,2);
+    akAxis[2][Yelt] = kES.GetEigenvector(1,2);
+    akAxis[2][Zelt] = kES.GetEigenvector(2,2);
+
+    afExtent[0] = kES.GetEigenvalue(0);
+    afExtent[1] = kES.GetEigenvalue(1);
+    afExtent[2] = kES.GetEigenvalue(2);
+}
+
+
+//
+bool GaussPointsFit (int iQuantity, const Vec3* akPoint,
+    const bool* abValid, Vec3& rkCenter, Vec3 akAxis[3],
+    float afExtent[3])
+{
+    // compute mean of points
+    rkCenter = ZeroVec3;
+    int i, iValidQuantity = 0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        if ( abValid[i] )
+        {
+            rkCenter += akPoint[i];
+            iValidQuantity++;
+        }
+    }
+    if ( iValidQuantity == 0 )
+        return false;
+
+    float fInvQuantity = 1.0/iValidQuantity;
+    rkCenter *= fInvQuantity;
+
+    // compute covariances of points
+    float fSumXX = 0.0, fSumXY = 0.0, fSumXZ = 0.0;
+    float fSumYY = 0.0, fSumYZ = 0.0, fSumZZ = 0.0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        if ( abValid[i] )
+        {
+            Vec3 kDiff = akPoint[i] - rkCenter;
+            fSumXX += kDiff[Xelt]*kDiff[Xelt];
+            fSumXY += kDiff[Xelt]*kDiff[Yelt];
+            fSumXZ += kDiff[Xelt]*kDiff[Zelt];
+            fSumYY += kDiff[Yelt]*kDiff[Yelt];
+            fSumYZ += kDiff[Yelt]*kDiff[Zelt];
+            fSumZZ += kDiff[Zelt]*kDiff[Zelt];
+        }
+    }
+    fSumXX *= fInvQuantity;
+    fSumXY *= fInvQuantity;
+    fSumXZ *= fInvQuantity;
+    fSumYY *= fInvQuantity;
+    fSumYZ *= fInvQuantity;
+    fSumZZ *= fInvQuantity;
+
+    // compute eigenvectors for covariance matrix
+    Eigen kES(3);
+    kES.Matrix(0,0) = fSumXX;
+    kES.Matrix(0,1) = fSumXY;
+    kES.Matrix(0,2) = fSumXZ;
+    kES.Matrix(1,0) = fSumXY;
+    kES.Matrix(1,1) = fSumYY;
+    kES.Matrix(1,2) = fSumYZ;
+    kES.Matrix(2,0) = fSumXZ;
+    kES.Matrix(2,1) = fSumYZ;
+    kES.Matrix(2,2) = fSumZZ;
+    kES.IncrSortEigenStuff3();
+
+    akAxis[0][Xelt] = kES.GetEigenvector(0,0);
+    akAxis[0][Yelt] = kES.GetEigenvector(1,0);
+    akAxis[0][Zelt] = kES.GetEigenvector(2,0);
+
+    akAxis[1][Xelt] = kES.GetEigenvector(0,1);
+    akAxis[1][Yelt] = kES.GetEigenvector(1,1);
+    akAxis[1][Zelt] = kES.GetEigenvector(2,1);
+
+    akAxis[2][Xelt] = kES.GetEigenvector(0,2);
+    akAxis[2][Yelt] = kES.GetEigenvector(1,2);
+    akAxis[2][Zelt] = kES.GetEigenvector(2,2);
+
+    afExtent[0] = kES.GetEigenvalue(0);
+    afExtent[1] = kES.GetEigenvalue(1);
+    afExtent[2] = kES.GetEigenvalue(2);
+
+    return true;
+}
+
+};
+
+/*
+void MgcGaussPointsFit (int iQuantity, const MgcVector2* akPoint,
+    MgcVector2& rkCenter, MgcVector2 akAxis[2], float afExtent[2])
+{
+    // compute mean of points
+    rkCenter = akPoint[0];
+    int i;
+    for (i = 1; i < iQuantity; i++)
+        rkCenter += akPoint[i];
+    float fInvQuantity = 1.0/iQuantity;
+    rkCenter *= fInvQuantity;
+
+    // compute covariances of points
+    float fSumXX = 0.0, fSumXY = 0.0, fSumYY = 0.0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        MgcVector2 kDiff = akPoint[i] - rkCenter;
+        fSumXX += kDiff.x*kDiff.x;
+        fSumXY += kDiff.x*kDiff.y;
+        fSumYY += kDiff.y*kDiff.y;
+    }
+    fSumXX *= fInvQuantity;
+    fSumXY *= fInvQuantity;
+    fSumYY *= fInvQuantity;
+
+    // solve eigensystem of covariance matrix
+    MgcEigen kES(2);
+    kES.Matrix(0,0) = fSumXX;
+    kES.Matrix(0,1) = fSumXY;
+    kES.Matrix(1,0) = fSumXY;
+    kES.Matrix(1,1) = fSumYY;
+    kES.IncrSortEigenStuff2();
+
+    akAxis[0].x = kES.GetEigenvector(0,0);
+    akAxis[0].y = kES.GetEigenvector(1,0);
+    akAxis[1].x = kES.GetEigenvector(0,1);
+    akAxis[1].y = kES.GetEigenvector(1,1);
+
+    afExtent[0] = kES.GetEigenvalue(0);
+    afExtent[1] = kES.GetEigenvalue(1);
+}
+*/
+
+
+/*
+bool MgcGaussPointsFit (int iQuantity, const MgcVector2* akPoint,
+    const bool* abValid, MgcVector2& rkCenter, MgcVector2 akAxis[2],
+    float afExtent[2])
+{
+    // compute mean of points
+    rkCenter = MgcVector2::ZERO;
+    int i, iValidQuantity = 0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        if ( abValid[i] )
+        {
+            rkCenter += akPoint[i];
+            iValidQuantity++;
+        }
+    }
+    if ( iValidQuantity == 0 )
+        return false;
+
+    float fInvQuantity = 1.0/iValidQuantity;
+    rkCenter *= fInvQuantity;
+
+    // compute covariances of points
+    float fSumXX = 0.0, fSumXY = 0.0, fSumYY = 0.0;
+    for (i = 0; i < iQuantity; i++)
+    {
+        if ( abValid[i] )
+        {
+            MgcVector2 kDiff = akPoint[i] - rkCenter;
+            fSumXX += kDiff.x*kDiff.x;
+            fSumXY += kDiff.x*kDiff.y;
+            fSumYY += kDiff.y*kDiff.y;
+        }
+    }
+    fSumXX *= fInvQuantity;
+    fSumXY *= fInvQuantity;
+    fSumYY *= fInvQuantity;
+
+    // solve eigensystem of covariance matrix
+    MgcEigen kES(2);
+    kES.Matrix(0,0) = fSumXX;
+    kES.Matrix(0,1) = fSumXY;
+    kES.Matrix(1,0) = fSumXY;
+    kES.Matrix(1,1) = fSumYY;
+    kES.IncrSortEigenStuff2();
+
+    akAxis[0].x = kES.GetEigenvector(0,0);
+    akAxis[0].y = kES.GetEigenvector(1,0);
+    akAxis[1].x = kES.GetEigenvector(0,1);
+    akAxis[1].y = kES.GetEigenvector(1,1);
+
+    afExtent[0] = kES.GetEigenvalue(0);
+    afExtent[1] = kES.GetEigenvalue(1);
+
+    return true;
+}
+*/
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Generate.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Generate.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Generate.h	(revision 4)
@@ -0,0 +1,1500 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Generate.h,v
+ * Date modified: 2006/04/24 14:33:04
+ * Version:       1.91
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_GENERATE_H_
+#define _GMTL_GENERATE_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Util/Assert.h>
+#include <gmtl/Util/StaticAssert.h>
+
+#include <gmtl/Vec.h>    // for Vec
+#include <gmtl/VecOps.h> // for lengthSquared
+#include <gmtl/Quat.h>
+#include <gmtl/QuatOps.h>
+#include <gmtl/Coord.h>
+#include <gmtl/Matrix.h>
+#include <gmtl/Util/Meta.h>
+#include <gmtl/Math.h>
+#include <gmtl/Xforms.h>
+
+#include <gmtl/EulerAngle.h>
+#include <gmtl/AxisAngle.h>
+
+namespace gmtl
+{
+   /** @ingroup Generate
+    *  @name Vec Generators
+    *  @{
+    */
+
+   /** create a vector from the vector component of a quaternion
+    * @returns a vector of the quaternion's axis. quat = [v,0] = [v0,v1,v2,0]
+    */
+   template <typename DATA_TYPE>
+   inline Vec<DATA_TYPE, 3> makeVec( const Quat<DATA_TYPE>& quat )
+   {
+      return Vec<DATA_TYPE, 3>( quat[Xelt], quat[Yelt], quat[Zelt] );
+   }
+
+   /** create a normalized vector from the given vector.
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Vec<DATA_TYPE, SIZE> makeNormal( Vec<DATA_TYPE, SIZE> vec )
+   {
+      normalize( vec );
+      return vec;
+   }
+
+   /**
+    * Computes the cross product between v1 and v2 and returns the result. Note
+    * that this only applies to 3-dimensional vectors.
+    *
+    * @pre  v1 and v2 must be 3-D vectors
+    * @post result = v1 x v2
+    *
+    * @param v1   the first vector
+    * @param v2   the second vector
+    *
+    * @return  the result of the cross product between v1 and v2
+    */
+   template<class DATA_TYPE>
+   Vec<DATA_TYPE,3> makeCross(const Vec<DATA_TYPE, 3>& v1,
+                              const Vec<DATA_TYPE, 3>& v2)
+   {
+      return Vec<DATA_TYPE,3>( ((v1[Yelt]*v2[Zelt]) - (v1[Zelt]*v2[Yelt])),
+                               ((v1[Zelt]*v2[Xelt]) - (v1[Xelt]*v2[Zelt])),
+                               ((v1[Xelt]*v2[Yelt]) - (v1[Yelt]*v2[Xelt])) );
+   }
+
+   /** Set vector using translation portion of the matrix.
+    * @pre if making an n x n matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS - 1
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS
+    * if making an n x n+1 matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS + 1
+    * @post if preconditions are not met, then function is undefined (will not compile)
+    */
+   template<typename VEC_TYPE, typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline VEC_TYPE& setTrans( VEC_TYPE& result, const Matrix<DATA_TYPE, ROWS, COLS>& arg )
+   {
+      // ASSERT: There are as many
+
+      // if n x n   then (homogeneous case) vecsize == rows-1 or (scale component case) vecsize == rows
+      // if n x n+1 then (homogeneous case) vecsize == rows   or (scale component case) vecsize == rows+1
+      gmtlASSERT( ((ROWS == COLS && ( VEC_TYPE::Size == (ROWS-1) ||  VEC_TYPE::Size == ROWS)) ||
+               (COLS == (ROWS+1) && ( VEC_TYPE::Size == ROWS ||  VEC_TYPE::Size == (ROWS+1)))) &&
+              "preconditions not met for vector size in call to makeTrans.  Read your documentation." );
+
+      // homogeneous case...
+      if ((ROWS == COLS &&  VEC_TYPE::Size == ROWS)              // Square matrix and vec so assume homogeneous vector. ex. 4x4 with vec 4
+          || (COLS == (ROWS+1) &&  VEC_TYPE::Size == (ROWS+1)))  // ex: 3x4 with vec4
+      {
+         result[VEC_TYPE::Size-1] = 1.0f;
+      }
+
+      // non-homogeneous case... (SIZE == ROWS),
+      //else
+      //{}
+
+      for (unsigned x = 0; x < COLS - 1; ++x)
+      {
+         result[x] = arg( x, COLS - 1 );
+      }
+
+      return result;
+   }
+
+   /** @} */
+
+   /** @ingroup Generate
+    *  @name Quat Generators
+    *  @{
+    */
+
+   /** Set pure quaternion
+   * @pre vec should be normalized
+   * @param quat     any quaternion object
+   * @param vec      a normalized vector representing an axis
+   * @post quat will have vec as its axis, and no rotation
+   */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE>& setPure( Quat<DATA_TYPE>& quat, const Vec<DATA_TYPE, 3>& vec )
+   {
+      quat.set( vec[0], vec[1], vec[2], 0 );
+      return quat;
+   }
+
+   /** create a pure quaternion
+   * @pre vec should be normalized
+   * @param vec      a normalized vector representing an axis
+   * @return a quaternion with vec as its axis, and no rotation
+   * @post quat = [v,0] = [v0,v1,v2,0]
+   */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE> makePure( const Vec<DATA_TYPE, 3>& vec )
+   {
+      return Quat<DATA_TYPE>( vec[0], vec[1], vec[2], 0 );
+   }
+
+   /** Normalize a quaternion
+    * @param quat       a quaternion
+    * @post quat is normalized
+    */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE> makeNormal( const Quat<DATA_TYPE>& quat )
+   {
+      Quat<DATA_TYPE> temporary( quat );
+      return normalize( temporary );
+   }
+
+   /** quaternion complex conjugate.
+    *  @param quat      any quaternion object
+    *  @post set result to the complex conjugate of result.
+    *  @post result'[x,y,z,w] == result[-x,-y,-z,w]
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE> makeConj( const Quat<DATA_TYPE>& quat )
+   {
+      Quat<DATA_TYPE> temporary( quat );
+      return conj( temporary );
+   }
+
+   /** create quaternion from the inverse of another quaternion.
+    *  @param quat      any quaternion object
+    *  @return    a quaternion that is the multiplicative inverse of quat
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE> makeInvert( const Quat<DATA_TYPE>& quat )
+   {
+      Quat<DATA_TYPE> temporary( quat );
+      return invert( temporary );
+   }
+
+   /** Convert an AxisAngle to a Quat.  sets a rotation quaternion from an angle and an axis.
+    * @pre AxisAngle::axis must be normalized to length == 1 prior to calling this.
+    * @post q = [ cos(rad/2), sin(rad/2) * [x,y,z] ]
+    */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE>& set( Quat<DATA_TYPE>& result, const AxisAngle<DATA_TYPE>& axisAngle )
+   {
+      gmtlASSERT( (Math::isEqual( lengthSquared( axisAngle.getAxis() ), (DATA_TYPE)1.0, (DATA_TYPE)0.0001 )) &&
+                   "you must pass in a normalized vector to setRot( quat, rad, vec )" );
+
+      DATA_TYPE half_angle = axisAngle.getAngle() * (DATA_TYPE)0.5;
+      DATA_TYPE sin_half_angle = Math::sin( half_angle );
+
+      result[Welt] = Math::cos( half_angle );
+      result[Xelt] = sin_half_angle * axisAngle.getAxis()[0];
+      result[Yelt] = sin_half_angle * axisAngle.getAxis()[1];
+      result[Zelt] = sin_half_angle * axisAngle.getAxis()[2];
+
+      // should automagically be normalized (unit magnitude) now...
+      return result;
+   }
+
+   /** Redundant duplication of the set(quat,axisangle) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(quat,axisangle).
+    */
+   template <typename DATA_TYPE>
+   inline Quat<DATA_TYPE>& setRot( Quat<DATA_TYPE>& result, const AxisAngle<DATA_TYPE>& axisAngle )
+   {
+      return gmtl::set( result, axisAngle );
+   }
+
+   /** Convert an EulerAngle rotation to a Quaternion rotation.
+    * Sets a rotation quaternion using euler angles (each angle in radians).
+    * @pre pass in your angles in the same order as the RotationOrder you specify
+    */
+   template <typename DATA_TYPE, typename ROT_ORDER>
+   inline Quat<DATA_TYPE>& set( Quat<DATA_TYPE>& result, const EulerAngle<DATA_TYPE, ROT_ORDER>& euler )
+   {
+      // this might be faster if put into the switch statement... (testme)
+      const int& order = ROT_ORDER::ID;
+      const DATA_TYPE xRot = (order == XYZ::ID) ? euler[0] : ((order == ZXY::ID) ? euler[1] : euler[2]);
+      const DATA_TYPE yRot = (order == XYZ::ID) ? euler[1] : ((order == ZXY::ID) ? euler[2] : euler[1]);
+      const DATA_TYPE zRot = (order == XYZ::ID) ? euler[2] : ((order == ZXY::ID) ? euler[0] : euler[0]);
+
+      // this could be written better for each rotation order, but this is really general...
+      Quat<DATA_TYPE> qx, qy, qz;
+
+      // precompute half angles
+      DATA_TYPE xOver2 = xRot * (DATA_TYPE)0.5;
+      DATA_TYPE yOver2 = yRot * (DATA_TYPE)0.5;
+      DATA_TYPE zOver2 = zRot * (DATA_TYPE)0.5;
+
+      // set the pitch quat
+      qx[Xelt] = Math::sin( xOver2 );
+      qx[Yelt] = (DATA_TYPE)0.0;
+      qx[Zelt] = (DATA_TYPE)0.0;
+      qx[Welt] = Math::cos( xOver2 );
+
+      // set the yaw quat
+      qy[Xelt] = (DATA_TYPE)0.0;
+      qy[Yelt] = Math::sin( yOver2 );
+      qy[Zelt] = (DATA_TYPE)0.0;
+      qy[Welt] = Math::cos( yOver2 );
+
+      // set the roll quat
+      qz[Xelt] = (DATA_TYPE)0.0;
+      qz[Yelt] = (DATA_TYPE)0.0;
+      qz[Zelt] = Math::sin( zOver2 );
+      qz[Welt] = Math::cos( zOver2 );
+
+      // compose the three in pyr order...
+      switch (order)
+      {
+      case XYZ::ID: result = qx * qy * qz; break;
+      case ZYX::ID: result = qz * qy * qx; break;
+      case ZXY::ID: result = qz * qx * qy; break;
+      default:
+         gmtlASSERT( false && "unknown rotation order passed to setRot" );
+         break;
+      }
+
+      // ensure the quaternion is normalized
+      normalize( result );
+      return result;
+   }
+
+   /** Redundant duplication of the set(quat,eulerangle) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(quat,eulerangle).
+    */
+   template <typename DATA_TYPE, typename ROT_ORDER>
+   inline Quat<DATA_TYPE>& setRot( Quat<DATA_TYPE>& result, const EulerAngle<DATA_TYPE, ROT_ORDER>& euler )
+   {
+      return gmtl::set( result, euler );
+   }
+
+   /** Convert a Matrix to a Quat.
+    *  Sets the rotation quaternion using the given matrix
+    *  (3x3, 3x4, 4x3, or 4x4 are all valid sizes).
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Quat<DATA_TYPE>& set( Quat<DATA_TYPE>& quat, const Matrix<DATA_TYPE, ROWS, COLS>& mat  )
+   {
+      gmtlASSERT( ((ROWS == 3 && COLS == 3) ||
+               (ROWS == 3 && COLS == 4) ||
+               (ROWS == 4 && COLS == 3) ||
+               (ROWS == 4 && COLS == 4)) &&
+               "pre conditions not met on set( quat, pos, mat ) which only sets a quaternion to the rotation part of a 3x3, 3x4, 4x3, or 4x4 matrix." );
+
+      DATA_TYPE tr( mat( 0, 0 ) + mat( 1, 1 ) + mat( 2, 2 ) ), s( 0.0f );
+
+      // If diagonal is positive
+      if (tr > (DATA_TYPE)0.0)
+      {
+         s = Math::sqrt( tr + (DATA_TYPE)1.0 );
+         quat[Welt] = s * (DATA_TYPE)0.5;
+         s = DATA_TYPE(0.5) / s;
+
+         quat[Xelt] = (mat( 2, 1 ) - mat( 1, 2 )) * s;
+         quat[Yelt] = (mat( 0, 2 ) - mat( 2, 0 )) * s;
+         quat[Zelt] = (mat( 1, 0 ) - mat( 0, 1 )) * s;
+      }
+
+      // when Diagonal is negative
+      else
+      {
+         static const unsigned int nxt[3] = { 1, 2, 0 };
+         unsigned int i( Xelt ), j, k;
+
+         if (mat( 1, 1 ) > mat( 0, 0 ))
+            i = 1;
+
+         if (mat( 2, 2 ) > mat( i, i ))
+            i = 2;
+
+         j = nxt[i];
+         k = nxt[j];
+
+         s = Math::sqrt( (mat( i, i )-(mat( j, j )+mat( k, k ))) + (DATA_TYPE)1.0 );
+
+         DATA_TYPE q[4];
+         q[i] = s * (DATA_TYPE)0.5;
+
+         if (s != (DATA_TYPE)0.0)
+            s = DATA_TYPE(0.5) / s;
+
+         q[3] = (mat( k, j ) - mat( j, k )) * s;
+         q[j] = (mat( j, i ) + mat( i, j )) * s;
+         q[k] = (mat( k, i ) + mat( i, k )) * s;
+
+         quat[Xelt] = q[0];
+         quat[Yelt] = q[1];
+         quat[Zelt] = q[2];
+         quat[Welt] = q[3];
+      }
+
+      return quat;
+   }
+
+   /** Redundant duplication of the set(quat,mat) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(quat,mat).
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Quat<DATA_TYPE>& setRot( Quat<DATA_TYPE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      return gmtl::set( result, mat );
+   }
+   /** @} */
+
+   /** @ingroup Generate
+    *  @name AxisAngle Generators
+    *  @{
+    */
+
+   /** Convert a rotation quaternion to an AxisAngle.
+    *
+    * @post returns an angle in radians, and a normalized axis equivilent to the quaternion's rotation.
+    * @post returns rad and xyz such that
+    * <ul>
+    * <li>  rad = acos( w ) * 2.0
+    * <li>  vec = v / (asin( w ) * 2.0)   [where v is the xyz or vector component of the quat]
+    * </ul>
+    * @post axisAngle = quat;
+    */
+   template <typename DATA_TYPE>
+   inline AxisAngle<DATA_TYPE>& set( AxisAngle<DATA_TYPE>& axisAngle, Quat<DATA_TYPE> quat )
+   {
+      // set sure we don't get a NaN result from acos...
+      if (Math::abs( quat[Welt] ) > (DATA_TYPE)1.0)
+      {
+         gmtl::normalize( quat );
+      }
+      gmtlASSERT( Math::abs( quat[Welt] ) <= (DATA_TYPE)1.0 && "acos returns NaN when quat[Welt] > 1, try normalizing your quat." );
+
+      // [acos( w ) * 2.0, v / (asin( w ) * 2.0)]
+
+      // set the angle - aCos is mathematically defined to be between 0 and PI
+      DATA_TYPE rad = Math::aCos( quat[Welt] ) * (DATA_TYPE)2.0;
+      axisAngle.setAngle( rad );
+
+      // set the axis: (use sin(rad) instead of asin(w))
+      DATA_TYPE sin_half_angle = Math::sin( rad * (DATA_TYPE)0.5 );
+      if (sin_half_angle >= (DATA_TYPE)0.0001) // because (PI >= rad >= 0)
+      {
+         DATA_TYPE sin_half_angle_inv = DATA_TYPE(1.0) / sin_half_angle;
+         Vec<DATA_TYPE, 3> axis( quat[Xelt] * sin_half_angle_inv,
+                                 quat[Yelt] * sin_half_angle_inv,
+                                 quat[Zelt] * sin_half_angle_inv );
+         normalize( axis );
+         axisAngle.setAxis( axis );
+      }
+
+      // avoid NAN
+      else
+      {
+         // one of the terms should be a 1,
+         // so we can maintain unit-ness
+         // in case w is 0 (which here w is 0)
+         axisAngle.setAxis( gmtl::Vec<DATA_TYPE, 3>(
+                             DATA_TYPE( 1.0 ) /*- gmtl::Math::abs( quat[Welt] )*/,
+                            (DATA_TYPE)0.0,
+                            (DATA_TYPE)0.0 ) );
+      }
+      return axisAngle;
+   }
+
+   /** Redundant duplication of the set(axisangle,quat) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(axisangle,quat) for clarity.
+    */
+   template <typename DATA_TYPE>
+   inline AxisAngle<DATA_TYPE>& setRot( AxisAngle<DATA_TYPE>& result, Quat<DATA_TYPE> quat )
+   {
+      return gmtl::set( result, quat );
+   }
+
+   /** make the axis of an AxisAngle normalized */
+   template <typename DATA_TYPE>
+   AxisAngle<DATA_TYPE> makeNormal( const AxisAngle<DATA_TYPE>& a )
+   {
+      return AxisAngle<DATA_TYPE>( a.getAngle(), makeNormal( a.getAxis() ) );
+   }
+   /** @} */
+
+   /** @ingroup Generate
+    *  @name EulerAngle Generators
+    *  @{
+    */
+
+   /** Convert Matrix to EulerAngle.
+    *  Set the Euler Angle from the given rotation portion (3x3) of the matrix.
+    *
+    * @param input  order, mat
+    * @param output param0, param1, param2
+    *
+    * @pre pass in your args in the same order as the RotationOrder you specify
+    * @post this function only reads 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    *       NOTE: Angles are returned in radians (this is always true in GMTL).
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, typename ROT_ORDER >
+   inline EulerAngle<DATA_TYPE, ROT_ORDER>& set( EulerAngle<DATA_TYPE, ROT_ORDER>& euler,
+                    const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      // @todo set this a compile time assert...
+      gmtlASSERT( ROWS >= 3 && COLS >= 3 && ROWS <= 4 && COLS <= 4 &&
+            "this is undefined for Matrix smaller than 3x3 or bigger than 4x4" );
+
+      // @todo metaprogram this!
+      const int& order = ROT_ORDER::ID;
+      switch (order)
+      {
+      case XYZ::ID:
+         {
+#if 0
+            euler[2] = Math::aTan2( -mat(0,1), mat(0,0) );       // -(-cy*sz)/(cy*cz) - cy falls out
+            euler[0] = Math::aTan2( -mat(1,2), mat(2,2) );       // -(sx*cy)/(cx*cy) - cy falls out
+            DATA_TYPE cz = Math::cos( euler[2] );
+            euler[1] = Math::aTan2( mat(0,2), mat(0,0) / cz );   // (sy)/((cy*cz)/cz)
+#else
+            DATA_TYPE x(0), y(0), z(0);
+            y = Math::aSin( mat(0,2));
+            if (y < gmtl::Math::PI_OVER_2)
+            {
+               if(y > -gmtl::Math::PI_OVER_2)
+               {
+                  x = Math::aTan2(-mat(1,2),mat(2,2));
+                  z = Math::aTan2(-mat(0,1),mat(0,0));
+               }
+               else  // Non-unique (x - z constant)
+               {
+                  x = -Math::aTan2(mat(1,0), mat(1,1));
+                  z = 0;
+               }
+            }
+            else
+            {
+               // not unique (x + z constant)
+               x = Math::aTan2(mat(1,0), mat(1,1));
+               z = 0;
+            }
+            euler[0] = x;
+            euler[1] = y;
+            euler[2] = z;
+
+#endif
+         }
+         break;
+      case ZYX::ID:
+         {
+#if 0
+            euler[0] = Math::aTan2( mat(1,0), mat(0,0) );        // (cy*sz)/(cy*cz) - cy falls out
+            euler[2] = Math::aTan2( mat(2,1), mat(2,2) );        // (sx*cy)/(cx*cy) - cy falls out
+            DATA_TYPE sx = Math::sin( euler[2] );
+            euler[1] = Math::aTan2( -mat(2,0), mat(2,1) / sx );  // -(-sy)/((sx*cy)/sx)
+#else
+            DATA_TYPE x(0), y(0), z(0);
+
+            y = Math::aSin(-mat(2,0));
+            if(y < Math::PI_OVER_2)
+            {
+               if(y>-Math::PI_OVER_2)
+               {
+                  z = Math::aTan2(mat(1,0), mat(0,0));
+                  x = Math::aTan2(mat(2,1), mat(2,2));
+               }
+               else  // not unique (x + z constant)
+               {
+                  z = Math::aTan2(-mat(0,1),-mat(0,2));
+                  x = 0;
+               }
+            }
+            else  // not unique (x - z constant)
+            {
+               z = -Math::aTan2(mat(0,1), mat(0,2));
+               x = 0;
+            }
+            euler[0] = z;
+            euler[1] = y;
+            euler[2] = x;
+#endif
+         }
+         break;
+      case ZXY::ID:
+         {
+#if 0
+         // Extract the rotation directly from the matrix
+            DATA_TYPE x_angle;
+            DATA_TYPE y_angle;
+            DATA_TYPE z_angle;
+            DATA_TYPE cos_y, sin_y;
+            DATA_TYPE cos_x, sin_x;
+            DATA_TYPE cos_z, sin_z;
+
+            sin_x = mat(2,1);
+            x_angle = Math::aSin( sin_x );     // Get x angle
+            cos_x = Math::cos( x_angle );
+
+            // Check if cos_x = Zero
+            if (cos_x != 0.0f)     // ASSERT: cos_x != 0
+            {
+                  // Get y Angle
+               cos_y = mat(2,2) / cos_x;
+               sin_y = -mat(2,0) / cos_x;
+               y_angle = Math::aTan2( cos_y, sin_y );
+
+                  // Get z Angle
+               cos_z = mat(1,1) / cos_x;
+               sin_z = -mat(0,1) / cos_x;
+               z_angle = Math::aTan2( cos_z, sin_z );
+            }
+            else
+            {
+               // Arbitrarily set z_angle = 0
+               z_angle = 0;
+
+                  // Get y Angle
+               cos_y = mat(0,0);
+               sin_y = mat(1,0);
+               y_angle = Math::aTan2( cos_y, sin_y );
+            }
+
+            euler[1] = x_angle;
+            euler[2] = y_angle;
+            euler[0] = z_angle;
+#else
+            DATA_TYPE x,y,z;
+
+            x = Math::aSin(mat(2,1));
+            if(x < Math::PI_OVER_2)
+            {
+               if(x > -Math::PI_OVER_2)
+               {
+                  z = Math::aTan2(-mat(0,1), mat(1,1));
+                  y = Math::aTan2(-mat(2,0), mat(2,2));
+               }
+               else  // not unique (y - z constant)
+               {
+                  z = -Math::aTan2(mat(0,2), mat(0,0));
+                  y = 0;
+               }
+            }
+            else  // not unique (y + z constant)
+            {
+               z = Math::aTan2(mat(0,2), mat(0,0));
+               y = 0;
+            }
+            euler[0] = z;
+            euler[1] = x;
+            euler[2] = y;
+#endif
+         }
+         break;
+      default:
+         gmtlASSERT( false && "unknown rotation order passed to setRot" );
+         break;
+      }
+      return euler;
+   }
+
+   /** Redundant duplication of the set(eulerangle,quat) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(eulerangle,quat) for clarity.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, typename ROT_ORDER >
+   inline EulerAngle<DATA_TYPE, ROT_ORDER>& setRot( EulerAngle<DATA_TYPE, ROT_ORDER>& result, const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      return gmtl::set( result, mat );
+   }
+   /** @} */
+
+   /** @ingroup Generate
+    *  @name Matrix Generators
+    *  @{
+    */
+
+   /** Set an arbitrary projection matrix
+    *  @result: set a projection matrix (similar to glFrustum).
+    */
+   template <typename T >
+   inline Matrix<T, 4,4>& setFrustum( Matrix<T, 4, 4>& result,
+                                                   T left, T top, T right,
+                                                   T bottom, T nr, T fr )
+   {
+      result.mData[0] = ( T( 2.0 ) * nr ) / ( right - left );
+      result.mData[1] = T( 0.0 );
+      result.mData[2] = T( 0.0 );
+      result.mData[3] = T( 0.0 );
+
+      result.mData[4] = T( 0.0 );
+      result.mData[5] = ( T( 2.0 ) * nr ) / ( top - bottom );
+      result.mData[6] = T( 0.0 );
+      result.mData[7] = T( 0.0 );
+
+      result.mData[8] = ( right + left ) / ( right - left );
+      result.mData[9] = ( top + bottom ) / ( top - bottom );
+      result.mData[10] = -( fr + nr ) / ( fr - nr );
+      result.mData[11] = T( -1.0 );
+
+      result.mData[12] = T( 0.0 );
+      result.mData[13] = T( 0.0 );
+      result.mData[14] = -( T( 2.0 ) * fr * nr ) / ( fr - nr );
+      result.mData[15] = T( 0.0 );
+
+      result.mState = Matrix<T, 4, 4>::FULL; // track state
+
+      return result;
+   }
+
+   /** Set an orthographic projection matrix
+    *  creates a transformation that produces a parallel projection matrix.
+    *  @nr = -nr is the value of the near clipping plane (positive value for near is negative in the z direction)
+    *  @fr = -fr is the value of the far clipping plane (positive value for far is negative in the z direction)
+    *  @result: set a orthographic matrix (similar to glOrtho).
+    */
+   template <typename T >
+   inline Matrix<T, 4,4>& setOrtho( Matrix<T,4,4>& result,
+                                          T left, T top, T right,
+                                          T bottom, T nr, T fr )
+   {
+      result.mData[1] = result.mData[2] = result.mData[3] =
+      result.mData[4] = result.mData[6] = result.mData[7] =
+      result.mData[8] = result.mData[9] = result.mData[11] = T(0);
+
+      T rl_inv = T(1) / (right - left);
+      T tb_inv = T(1) / (top - bottom);
+      T nf_inv = T(1) / (fr - nr);
+
+      result.mData[0] =  T(2) * rl_inv;
+      result.mData[5] =  T(2) * tb_inv;
+      result.mData[10] = -T(2) * nf_inv;
+
+      result.mData[12] = -(right + left) * rl_inv;
+      result.mData[13] = -(top + bottom) * tb_inv;
+      result.mData[14] = -(fr + nr) * nf_inv;
+      result.mData[15] = T(1);
+
+      return result;
+   }
+
+   /** Set a symmetric perspective projection matrix
+    * @param fovy
+    *   The field of view angle, in degrees, about the y-axis.
+    * @param aspect
+    *   The aspect ratio that determines the field of view about the x-axis.
+    *   The aspect ratio is the ratio of x (width) to y (height).
+    * @param zNear
+    *   The distance from the viewer to the near clipping plane (always positive).
+    * @param zFar
+    *   The distance from the viewer to the far clipping plane (always positive).
+    * @result Set matrix to perspective transform
+    */
+   template <typename T>
+   inline Matrix<T, 4,4>& setPerspective( Matrix<T, 4, 4>& result,
+                                                 T fovy, T aspect, T nr, T fr )
+   {
+      gmtlASSERT( nr > 0 && fr > nr && "invalid near and far values" );
+      T theta = Math::deg2Rad( fovy * T( 0.5 ) );
+      T tangentTheta = Math::tan( theta );
+
+      // tan(theta) = right / nr
+      // top = tan(theta) * nr
+      // right = tan(theta) * nr * aspect
+
+      T top = tangentTheta * nr;
+      T right = top * aspect; // aspect determines the fieald of view in the x-axis
+
+      // TODO: args need to match...
+      return setFrustum( result, -right, top, right, -top, nr, fr );
+   }
+
+
+   /*
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned SIZE, typename REP >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setTrans( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                   const VecBase<DATA_TYPE, SIZE, REP>& trans )
+   {
+      const Vec<DATA_TYPE,SIZE,meta::DefaultVecTag> temp_vec(trans);
+      return setTrans(result,trans);
+   }
+   */
+
+   /** Set matrix translation from vec.
+    * @pre if making an n x n matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS - 1
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS
+    * if making an n x n+1 matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS + 1
+    * @post if preconditions are not met, then function is undefined (will not compile)
+    */
+#ifdef GMTL_NO_METAPROG
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned SIZE >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setTrans( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                   const VecBase<DATA_TYPE, SIZE>& trans )
+#else
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned SIZE, typename REP >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setTrans( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                   const VecBase<DATA_TYPE, SIZE, REP>& trans )
+#endif
+   {
+      /* @todo make this a compile time assert... */
+      // if n x n   then (homogeneous case) vecsize == rows-1 or (scale component case) vecsize == rows
+      // if n x n+1 then (homogeneous case) vecsize == rows   or (scale component case) vecsize == rows+1
+      gmtlASSERT( ((ROWS == COLS && (SIZE == (ROWS-1) || SIZE == ROWS)) ||
+               (COLS == (ROWS+1) && (SIZE == ROWS || SIZE == (ROWS+1)))) &&
+              "preconditions not met for vector size in call to makeTrans.  Read your documentation." );
+
+      // homogeneous case...
+      if ((ROWS == COLS && SIZE == ROWS) /* Square matrix and vec so assume homogeneous vector. ex. 4x4 with vec 4 */
+          || (COLS == (ROWS+1) && SIZE == (ROWS+1)))  /* ex: 3x4 with vec4 */
+      {
+         DATA_TYPE homog_val = trans[SIZE-1];
+         for (unsigned x = 0; x < COLS - 1; ++x)
+            result( x, COLS - 1 ) = trans[x] / homog_val;
+      }
+
+      // non-homogeneous case...
+      else
+      {
+         for (unsigned x = 0; x < COLS - 1; ++x)
+            result( x, COLS - 1 ) = trans[x];
+      }
+      // track state, only override identity
+      switch (result.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL: result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY:   result.mState = Matrix<DATA_TYPE, ROWS, COLS>::TRANS; break;
+      }
+      return result;
+   }
+
+   /** Set the scale part of a matrix.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned SIZE >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setScale( Matrix<DATA_TYPE, ROWS, COLS>& result, const Vec<DATA_TYPE, SIZE>& scale )
+   {
+      gmtlASSERT( ((SIZE == (ROWS-1) && SIZE == (COLS-1)) || (SIZE == (ROWS-1) && SIZE == COLS) || (SIZE == (COLS-1) && SIZE == ROWS)) && "the scale params must fit within the matrix, check your sizes." );
+      for (unsigned x = 0; x < SIZE; ++x)
+      {
+         result( x, x ) = scale[x];
+      }
+      // track state: affine matrix with non-uniform scale now.
+      result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE;
+      result.mState |= Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE;
+      return result;
+   }
+
+   /** Sets the scale part of a matrix.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setScale( Matrix<DATA_TYPE, ROWS, COLS>& result, const DATA_TYPE scale )
+   {
+      for (unsigned x = 0; x < Math::Min( ROWS, COLS, Math::Max( ROWS, COLS ) - 1 ); ++x) // account for 2x4 or other weird sizes...
+      {
+         result( x, x ) = scale;
+      }
+      // track state: affine matrix with non-uniform scale now.
+      result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE;
+      result.mState |= Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE;
+      return result;
+   }
+
+   /** Create a scale matrix.
+    *  @param scale  You'll typically pass in a Vec or a float here.
+    *  @seealso      setScale() for all possible argument types for this function.
+    */
+   template <typename MATRIX_TYPE, typename INPUT_TYPE>
+   inline MATRIX_TYPE makeScale( const INPUT_TYPE& scale,
+                               Type2Type< MATRIX_TYPE > t = Type2Type< MATRIX_TYPE >() )
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      MATRIX_TYPE temporary;
+      return setScale( temporary, scale );
+   }
+
+   /** Set the rotation portion of a rotation matrix using an axis and an angle (in radians).
+    *  Only writes to the rotation matrix (3x3) defined by the rotation part of M
+    * @post this function only writes to 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    * @pre you must pass a normalized vector in for the axis, results are undefined if not.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setRot( Matrix<DATA_TYPE, ROWS, COLS>& result, const AxisAngle<DATA_TYPE>& axisAngle )
+   {
+      /* @todo set this a compile time assert... */
+      gmtlASSERT( ROWS >= 3 && COLS >= 3 && ROWS <= 4 && COLS <= 4 &&
+                     "this func is undefined for Matrix smaller than 3x3 or bigger than 4x4" );
+      gmtlASSERT( Math::isEqual( lengthSquared( axisAngle.getAxis() ), (DATA_TYPE)1.0, (DATA_TYPE)0.001 ) /* &&
+                     "you must pass in a normalized vector to setRot( mat, rad, vec )" */ );
+
+      // GGI: pg 466
+      DATA_TYPE s = Math::sin( axisAngle.getAngle() );
+      DATA_TYPE c = Math::cos( axisAngle.getAngle() );
+      DATA_TYPE t = DATA_TYPE( 1.0 ) - c;
+      DATA_TYPE x = axisAngle.getAxis()[0];
+      DATA_TYPE y = axisAngle.getAxis()[1];
+      DATA_TYPE z = axisAngle.getAxis()[2];
+
+      /* From: Introduction to robotic.  Craig.  Pg. 52 */
+      result( 0, 0 ) = (t*x*x)+c;     result( 0, 1 ) = (t*x*y)-(s*z); result( 0, 2 ) = (t*x*z)+(s*y);
+      result( 1, 0 ) = (t*x*y)+(s*z); result( 1, 1 ) = (t*y*y)+c;     result( 1, 2 ) = (t*y*z)-(s*x);
+      result( 2, 0 ) = (t*x*z)-(s*y); result( 2, 1 ) = (t*y*z)+(s*x); result( 2, 2 ) = (t*z*z)+c;
+
+      // track state
+      switch (result.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::TRANS:    result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY: result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL; break;
+      }
+      return result;
+   }
+
+   /** Set (only) the rotation part of a matrix using an EulerAngle (angles are in radians).
+    * @post this function only produces 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    * @see EulerAngle for angle ordering (usually ordered based on RotationOrder)
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, typename ROT_ORDER >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setRot( Matrix<DATA_TYPE, ROWS, COLS>& result, const EulerAngle<DATA_TYPE, ROT_ORDER>& euler )
+   {
+      // @todo set this a compile time assert...
+      gmtlASSERT( ROWS >= 3 && COLS >= 3 && ROWS <= 4 && COLS <= 4 && "this is undefined for Matrix smaller than 3x3 or bigger than 4x4" );
+
+      // this might be faster if put into the switch statement... (testme)
+      const int& order = ROT_ORDER::ID;
+      const DATA_TYPE xRot = (order == XYZ::ID) ? euler[0] : ((order == ZXY::ID) ? euler[1] : euler[2]);
+      const DATA_TYPE yRot = (order == XYZ::ID) ? euler[1] : ((order == ZXY::ID) ? euler[2] : euler[1]);
+      const DATA_TYPE zRot = (order == XYZ::ID) ? euler[2] : ((order == ZXY::ID) ? euler[0] : euler[0]);
+
+      DATA_TYPE sx = Math::sin( xRot );  DATA_TYPE cx = Math::cos( xRot );
+      DATA_TYPE sy = Math::sin( yRot );  DATA_TYPE cy = Math::cos( yRot );
+      DATA_TYPE sz = Math::sin( zRot );  DATA_TYPE cz = Math::cos( zRot );
+
+      // @todo metaprogram this!
+      switch (order)
+      {
+      case XYZ::ID:
+         // Derived by simply multiplying out the matrices by hand X * Y * Z
+         result( 0, 0 ) = cy*cz;             result( 0, 1 ) = -cy*sz;            result( 0, 2 ) = sy;
+         result( 1, 0 ) = sx*sy*cz + cx*sz;  result( 1, 1 ) = -sx*sy*sz + cx*cz; result( 1, 2 ) = -sx*cy;
+         result( 2, 0 ) = -cx*sy*cz + sx*sz; result( 2, 1 ) = cx*sy*sz + sx*cz;  result( 2, 2 ) = cx*cy;
+         break;
+      case ZYX::ID:
+         // Derived by simply multiplying out the matrices by hand Z * Y * Z
+         result( 0, 0 ) = cy*cz; result( 0, 1 ) = -cx*sz + sx*sy*cz; result( 0, 2 ) = sx*sz + cx*sy*cz;
+         result( 1, 0 ) = cy*sz; result( 1, 1 ) = cx*cz + sx*sy*sz;  result( 1, 2 ) = -sx*cz + cx*sy*sz;
+         result( 2, 0 ) = -sy;   result( 2, 1 ) = sx*cy;             result( 2, 2 ) = cx*cy;
+         break;
+      case ZXY::ID:
+         // Derived by simply multiplying out the matrices by hand Z * X * Y
+         result( 0, 0 ) = cy*cz - sx*sy*sz; result( 0, 1 ) = -cx*sz; result( 0, 2 ) = sy*cz + sx*cy*sz;
+         result( 1, 0 ) = cy*sz + sx*sy*cz; result( 1, 1 ) = cx*cz;  result( 1, 2 ) = sy*sz - sx*cy*cz;
+         result( 2, 0 ) = -cx*sy;           result( 2, 1 ) = sx;     result( 2, 2 ) = cx*cy;
+         break;
+      default:
+         gmtlASSERT( false && "unknown rotation order passed to setRot" );
+         break;
+      }
+
+      // track state
+      switch (result.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::TRANS:    result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY: result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL; break;
+      }
+      return result;
+   }
+
+   /** Convert an AxisAngle to a rotation matrix.
+    * @post this function only writes to 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    * @pre AxisAngle must be normalized (the axis part), results are undefined if not.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& set( Matrix<DATA_TYPE, ROWS, COLS>& result, const AxisAngle<DATA_TYPE>& axisAngle )
+   {
+      gmtl::identity( result );
+      return setRot( result, axisAngle );
+   }
+
+   /** Convert an EulerAngle to a rotation matrix.
+    * @post this function only writes to 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS, typename ROT_ORDER >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& set( Matrix<DATA_TYPE, ROWS, COLS>& result, const EulerAngle<DATA_TYPE, ROT_ORDER>& euler )
+   {
+      gmtl::identity( result );
+      return setRot( result, euler );
+   }
+
+   /**
+    * Extracts the Y axis rotation information from the matrix.
+    * @post Returned value is from -PI to PI, where 0 is none.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline DATA_TYPE makeYRot( const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      const gmtl::Vec<DATA_TYPE, 3> forward_point(0.0f, 0.0f, -1.0f);   // -Z
+      const gmtl::Vec<DATA_TYPE, 3> origin_point(0.0f, 0.0f, 0.0f);
+      gmtl::Vec<DATA_TYPE, 3> end_point, start_point;
+
+      gmtl::xform(end_point, mat, forward_point);
+      gmtl::xform(start_point, mat, origin_point);
+      gmtl::Vec<DATA_TYPE, 3> direction_vector = end_point - start_point;
+
+      // Constrain the direction to XZ-plane only.
+      direction_vector[1] = 0.0f;                  // Eliminate Y value
+      gmtl::normalize(direction_vector);
+      DATA_TYPE y_rot = gmtl::Math::aCos(gmtl::dot(direction_vector,
+                                                   forward_point));
+
+      gmtl::Vec<DATA_TYPE, 3> which_side = gmtl::makeCross(forward_point,
+                                                           direction_vector);
+
+      // If direction vector to "right" (negative) side of forward
+      if ( which_side[1] < 0.0f )
+      {
+         y_rot = -y_rot;
+      }
+
+      return y_rot;
+   }
+
+   /**
+    * Extracts the X-axis rotation information from the matrix.
+    * @post Returned value is from -PI to PI, where 0 is no rotation.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline DATA_TYPE makeXRot( const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      const gmtl::Vec<DATA_TYPE, 3> forward_point(0.0f, 0.0f, -1.0f);   // -Z
+      const gmtl::Vec<DATA_TYPE, 3> origin_point(0.0f, 0.0f, 0.0f);
+      gmtl::Vec<DATA_TYPE, 3> end_point, start_point;
+
+      gmtl::xform(end_point, mat, forward_point);
+      gmtl::xform(start_point, mat, origin_point);
+      gmtl::Vec<DATA_TYPE, 3> direction_vector = end_point - start_point;
+
+      // Constrain the direction to YZ-plane only.
+      direction_vector[0] = 0.0f;                  // Eliminate X value
+      gmtl::normalize(direction_vector);
+      DATA_TYPE x_rot = gmtl::Math::aCos(gmtl::dot(direction_vector,
+                                                   forward_point));
+
+      gmtl::Vec<DATA_TYPE, 3> which_side = gmtl::makeCross(forward_point,
+                                                           direction_vector);
+
+      // If direction vector to "bottom" (negative) side of forward
+      if ( which_side[0] < 0.0f )
+      {
+         x_rot = -x_rot;
+      }
+
+      return x_rot;
+   }
+
+   /**
+    * Extracts the Z-axis rotation information from the matrix.
+    * @post Returned value is from -PI to PI, where 0 is no rotation.
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline DATA_TYPE makeZRot( const Matrix<DATA_TYPE, ROWS, COLS>& mat )
+   {
+      const gmtl::Vec<DATA_TYPE, 3> forward_point(1.0f, 0.0f, 0.0f);   // +x
+      const gmtl::Vec<DATA_TYPE, 3> origin_point(0.0f, 0.0f, 0.0f);
+      gmtl::Vec<DATA_TYPE, 3> end_point, start_point;
+
+      gmtl::xform(end_point, mat, forward_point);
+      gmtl::xform(start_point, mat, origin_point);
+      gmtl::Vec<DATA_TYPE, 3> direction_vector = end_point - start_point;
+
+      // Constrain the direction to XY-plane only.
+      direction_vector[2] = 0.0f;                  // Eliminate Z value
+      gmtl::normalize(direction_vector);
+      DATA_TYPE z_rot = gmtl::Math::aCos(gmtl::dot(direction_vector,
+                                                   forward_point));
+
+      gmtl::Vec<DATA_TYPE, 3> which_side = gmtl::makeCross(forward_point,
+                                                           direction_vector);
+
+      // If direction vector to "right" (negative) side of forward
+      if ( which_side[2] < 0.0f )
+      {
+         z_rot = -z_rot;
+      }
+
+      return z_rot;
+   }
+
+   /** create a rotation matrix that will rotate from SrcAxis to DestAxis.
+    *  xSrcAxis, ySrcAxis, zSrcAxis is the base rotation to go from and defaults to xSrcAxis(1,0,0), ySrcAxis(0,1,0), zSrcAxis(0,0,1) if you only pass in 3 axes.
+    *
+    *  If the two coordinate frames are labeled: SRC and TARGET, the matrix produced is:  src_M_target
+    *  this means that it will transform a point in TARGET to SRC but moves the base frame from SRC to TARGET.
+    *
+    *  @pre pass in 3 axes, and setDirCos will give you the rotation from MATRIX_IDENTITY to DestAxis
+    *  @pre pass in 6 axes, and setDirCos will give you the rotation from your 3-axis rotation to your second 3-axis rotation
+    *  @post this function only produces 3x3, 3x4, 4x3, and 4x4 matrices
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setDirCos( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                     const Vec<DATA_TYPE, 3>& xDestAxis,
+                                                     const Vec<DATA_TYPE, 3>& yDestAxis, const Vec<DATA_TYPE, 3>& zDestAxis,
+                                                     const Vec<DATA_TYPE, 3>& xSrcAxis = Vec<DATA_TYPE, 3>(1,0,0),
+                                                     const Vec<DATA_TYPE, 3>& ySrcAxis = Vec<DATA_TYPE, 3>(0,1,0),
+                                                     const Vec<DATA_TYPE, 3>& zSrcAxis = Vec<DATA_TYPE, 3>(0,0,1) )
+   {
+      // @todo set this a compile time assert...
+      gmtlASSERT( ROWS >= 3 && COLS >= 3 && ROWS <= 4 && COLS <= 4 && "this is undefined for Matrix smaller than 3x3 or bigger than 4x4" );
+
+      DATA_TYPE Xa, Xb, Xc;    // Direction cosines of the secondary x-axis
+      DATA_TYPE Ya, Yb, Yc;    // Direction cosines of the secondary y-axis
+      DATA_TYPE Za, Zb, Zc;    // Direction cosines of the secondary z-axis
+
+      Xa = dot(xDestAxis, xSrcAxis);  Xb = dot(xDestAxis, ySrcAxis);  Xc = dot(xDestAxis, zSrcAxis);
+      Ya = dot(yDestAxis, xSrcAxis);  Yb = dot(yDestAxis, ySrcAxis);  Yc = dot(yDestAxis, zSrcAxis);
+      Za = dot(zDestAxis, xSrcAxis);  Zb = dot(zDestAxis, ySrcAxis);  Zc = dot(zDestAxis, zSrcAxis);
+
+      // Set the matrix correctly
+      result( 0, 0 ) = Xa; result( 0, 1 ) = Ya; result( 0, 2 ) = Za;
+      result( 1, 0 ) = Xb; result( 1, 1 ) = Yb; result( 1, 2 ) = Zb;
+      result( 2, 0 ) = Xc; result( 2, 1 ) = Yc; result( 2, 2 ) = Zc;
+
+      // track state
+      switch (result.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::TRANS:    result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY: result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL; break;
+      }
+
+      return result;
+   }
+
+   /** set the matrix given the raw coordinate axes.
+    * @post this function only produces 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    * @post these axes are copied direct to the 3x3 in the matrix
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS>& setAxes( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                  const Vec<DATA_TYPE, 3>& xAxis,
+                                                  const Vec<DATA_TYPE, 3>& yAxis,
+                                                  const Vec<DATA_TYPE, 3>& zAxis )
+   {
+      // @todo set this a compile time assert...
+      gmtlASSERT( ROWS >= 3 && COLS >= 3 && ROWS <= 4 && COLS <= 4 && "this is undefined for Matrix smaller than 3x3 or bigger than 4x4" );
+
+      result( 0, 0 ) = xAxis[0];
+      result( 1, 0 ) = xAxis[1];
+      result( 2, 0 ) = xAxis[2];
+
+      result( 0, 1 ) = yAxis[0];
+      result( 1, 1 ) = yAxis[1];
+      result( 2, 1 ) = yAxis[2];
+
+      result( 0, 2 ) = zAxis[0];
+      result( 1, 2 ) = zAxis[1];
+      result( 2, 2 ) = zAxis[2];
+
+      // track state
+      switch (result.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::TRANS:    result.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY: result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL; break;
+      }
+      return result;
+   }
+
+   /** set the matrix given the raw coordinate axes.
+    * @post this function only produces 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    * @post these axes are copied direct to the 3x3 in the matrix
+    */
+   template< typename ROTATION_TYPE >
+   inline ROTATION_TYPE makeAxes( const Vec<typename ROTATION_TYPE::DataType, 3>& xAxis,
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& yAxis,
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& zAxis,
+                                  Type2Type< ROTATION_TYPE > t = Type2Type< ROTATION_TYPE >() )
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      ROTATION_TYPE temporary;
+      return setAxes( temporary, xAxis, yAxis, zAxis );
+   }
+
+   /** create a matrix transposed from the source.
+    *  @post returns the transpose of m
+    *  @see Quat
+    */
+   template < typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS> makeTranspose( const Matrix<DATA_TYPE, ROWS, COLS>& m )
+   {
+      Matrix<DATA_TYPE, ROWS, COLS> temporary( m );
+      return transpose( temporary );
+   }
+
+   /**
+    * Creates a matrix that is the inverse of the given source matrix.
+    *
+    * @param src     the matrix to compute the inverse of
+    *
+    * @return  the inverse of source
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   inline Matrix<DATA_TYPE, ROWS, COLS> makeInvert(const Matrix<DATA_TYPE, ROWS, COLS>& src)
+   {
+      Matrix<DATA_TYPE, ROWS, COLS> result;
+      return invert( result, src );
+   }
+
+   /** Set the rotation portion of a matrix (3x3) from a rotation quaternion.
+    * @pre only 3x3, 3x4, 4x3, or 4x4 matrices are allowed, function is undefined otherwise.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   Matrix<DATA_TYPE, ROWS, COLS>& setRot( Matrix<DATA_TYPE, ROWS, COLS>& mat, const Quat<DATA_TYPE>& q )
+   {
+      gmtlASSERT( ((ROWS == 3 && COLS == 3) ||
+               (ROWS == 3 && COLS == 4) ||
+               (ROWS == 4 && COLS == 3) ||
+               (ROWS == 4 && COLS == 4)) &&
+               "pre conditions not met on set( mat, quat ) which only sets a quaternion to the rotation part of a 3x3, 3x4, 4x3, or 4x4 matrix." );
+
+      // From Watt & Watt
+      DATA_TYPE wx, wy, wz, xx, yy, yz, xy, xz, zz, xs, ys, zs;
+
+      xs = q[Xelt] + q[Xelt]; ys = q[Yelt] + q[Yelt]; zs = q[Zelt] + q[Zelt];
+      xx = q[Xelt] * xs;      xy = q[Xelt] * ys;      xz = q[Xelt] * zs;
+      yy = q[Yelt] * ys;      yz = q[Yelt] * zs;      zz = q[Zelt] * zs;
+      wx = q[Welt] * xs;      wy = q[Welt] * ys;      wz = q[Welt] * zs;
+
+      mat( 0, 0 ) = DATA_TYPE(1.0) - (yy + zz);
+      mat( 1, 0 ) = xy + wz;
+      mat( 2, 0 ) = xz - wy;
+
+      mat( 0, 1 ) = xy - wz;
+      mat( 1, 1 ) = DATA_TYPE(1.0) - (xx + zz);
+      mat( 2, 1 ) = yz + wx;
+
+      mat( 0, 2 ) = xz + wy;
+      mat( 1, 2 ) = yz - wx;
+      mat( 2, 2 ) = DATA_TYPE(1.0) - (xx + yy);
+
+      // track state
+      switch (mat.mState)
+      {
+      case Matrix<DATA_TYPE, ROWS, COLS>::TRANS:    mat.mState = Matrix<DATA_TYPE, ROWS, COLS>::AFFINE; break;
+      case Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY: mat.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL; break;
+      }
+      return mat;
+   }
+
+   /** Convert a Coord to a Matrix
+    * Note: It is set directly, but this is equivalent to T*R where T is the translation matrix and R is the rotation matrix.
+    * @see Coord
+    * @see Matrix
+    */
+   template <typename DATATYPE, typename POS_TYPE, typename ROT_TYPE, unsigned MATCOLS, unsigned MATROWS >
+   inline Matrix<DATATYPE, MATROWS, MATCOLS>& set( Matrix<DATATYPE, MATROWS, MATCOLS>& mat,
+                                                   const Coord<POS_TYPE, ROT_TYPE>& coord )
+   {
+      // set to ident first...
+      gmtl::identity( mat );
+
+      // set translation
+      // @todo metaprogram this out for 3x3 and 2x2 matrices
+      if (MATCOLS == 4)
+      {
+         setTrans( mat, coord.getPos() );// filtered (only sets the trans part).
+      }
+      setRot( mat, coord.getRot() ); // filtered (only sets the rot part).
+      return mat;
+   }
+
+   /** Convert a Quat to a rotation Matrix.
+    *  @pre only 3x3, 3x4, 4x3, or 4x4 matrices are allowed, function is undefined otherwise.
+    *  @post Matrix is entirely overwritten.
+    *  @todo Implement using setRot
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   Matrix<DATA_TYPE, ROWS, COLS>& set( Matrix<DATA_TYPE, ROWS, COLS>& mat, const Quat<DATA_TYPE>& q )
+   {
+      if (ROWS == 4)
+      {
+         mat( 3, 0 ) = DATA_TYPE(0.0);
+         mat( 3, 1 ) = DATA_TYPE(0.0);
+         mat( 3, 2 ) = DATA_TYPE(0.0);
+      }
+
+      if (COLS == 4)
+      {
+         mat( 0, 3 ) = DATA_TYPE(0.0);
+         mat( 1, 3 ) = DATA_TYPE(0.0);
+         mat( 2, 3 ) = DATA_TYPE(0.0);
+      }
+
+      if (ROWS == 4 && COLS == 4)
+         mat( 3, 3 ) = DATA_TYPE(1.0);
+
+      // track state
+      mat.mState = Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY;
+
+      return setRot( mat, q );
+   }
+
+   /** @} */
+
+   /** @ingroup Generate
+    *  @name Coord Generators
+    *  @{
+    */
+
+   /** convert Matrix to Coord */
+   template <typename DATATYPE, typename POS_TYPE, typename ROT_TYPE, unsigned MATCOLS, unsigned MATROWS >
+   inline Coord<POS_TYPE, ROT_TYPE>& set( Coord<POS_TYPE, ROT_TYPE>& eulercoord, const Matrix<DATATYPE, MATROWS, MATCOLS>& mat )
+   {
+      gmtl::setTrans( eulercoord.pos(), mat );
+      gmtl::set( eulercoord.rot(), mat );
+      return eulercoord;
+   }
+
+   /** Redundant duplication of the set(coord,mat) function, this is provided only for template compatibility.
+    *  unless you're writing template functions, you should use set(coord,mat) for clarity.
+    */
+   template <typename DATATYPE, typename POS_TYPE, typename ROT_TYPE, unsigned MATCOLS, unsigned MATROWS >
+   inline Coord<POS_TYPE, ROT_TYPE>& setRot( Coord<POS_TYPE, ROT_TYPE>& result, const Matrix<DATATYPE, MATROWS, MATCOLS>& mat )
+   {
+      return gmtl::set( result, mat );
+   }
+
+   /** @} */
+
+   /** @ingroup Generate
+     *  @name Generic Generators (any type)
+     *  @{
+     */
+
+   /** Construct an object from another object of a different type.
+    *  This allows us to automatically convert from any type to any
+    *  other type.
+    *  @pre must have a set() function defined that converts between the
+    *       two types.
+    *  @param src    the object to use for creation
+    *  @return a new object with values based on the src variable
+    *  @see OpenSGGenerate.h for an example
+    */
+   template <typename TARGET_TYPE, typename SOURCE_TYPE>
+   inline TARGET_TYPE make( const SOURCE_TYPE& src,
+                           Type2Type< TARGET_TYPE > t = Type2Type< TARGET_TYPE >() )
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      TARGET_TYPE target;
+      return gmtl::set( target, src );
+   }
+
+   /** Create a rotation datatype from another rotation datatype.
+    * @post converts the source rotation to a to another type (usually Matrix, Quat, Euler, AxisAngle),
+    * @post returns a temporary object.
+    */
+   template <typename ROTATION_TYPE, typename SOURCE_TYPE >
+   inline ROTATION_TYPE makeRot( const SOURCE_TYPE& coord,
+                                Type2Type< ROTATION_TYPE > t = Type2Type< ROTATION_TYPE >() )
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      ROTATION_TYPE temporary;
+      return gmtl::set( temporary, coord );
+   }
+
+   /** Create a rotation matrix or quaternion (or any other rotation data type) using direction cosines.
+    *
+    *  If the two coordinate frames are labeled: SRC and TARGET, the matrix produced is:  src_M_target
+    *  this means that it will transform a point in TARGET to SRC but moves the base frame from SRC to TARGET.
+    *
+    * @param DestAxis required to specify
+    * @param SrcAxis optional to specify
+    * @pre specify 1 axis (3 vectors), or 2 axes (6 vectors).
+    * @post Creates a rotation from SrcAxis to DestAxis
+    * @post this function only produces 3x3, 3x4, 4x3, and 4x4 matrices, and is undefined otherwise
+    */
+   template< typename ROTATION_TYPE >
+   inline ROTATION_TYPE makeDirCos( const Vec<typename ROTATION_TYPE::DataType, 3>& xDestAxis,
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& yDestAxis,
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& zDestAxis,
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& xSrcAxis = Vec<typename ROTATION_TYPE::DataType, 3>(1,0,0),
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& ySrcAxis = Vec<typename ROTATION_TYPE::DataType, 3>(0,1,0),
+                                  const Vec<typename ROTATION_TYPE::DataType, 3>& zSrcAxis = Vec<typename ROTATION_TYPE::DataType, 3>(0,0,1),
+                               Type2Type< ROTATION_TYPE > t = Type2Type< ROTATION_TYPE >() )
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      ROTATION_TYPE temporary;
+      return setDirCos( temporary, xDestAxis, yDestAxis, zDestAxis, xSrcAxis, ySrcAxis, zSrcAxis );
+   }
+
+   /**
+    * Make a translation datatype from another translation datatype.
+    * Typically this is from Matrix to Vec or Vec to Matrix.
+    * This function reads only translation information from the src datatype.
+    *
+    * @param arg  the matrix to extract the translation from
+    *
+    * @pre if making an n x n matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS - 1
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS
+    * <br>if making an n x n+1 matrix, then for
+    *    - <b>vector is homogeneous:</b> SIZE of vector needs to equal number of Matrix ROWS
+    *    - <b>vector has scale component:</b> SIZE of vector needs to equal number of Matrix ROWS + 1
+    * @post if preconditions are not met, then function is undefined (will not compile)
+    */
+   template<typename TRANS_TYPE, typename SRC_TYPE >
+   inline TRANS_TYPE makeTrans( const SRC_TYPE& arg,
+                             Type2Type< TRANS_TYPE > t = Type2Type< TRANS_TYPE >())
+   {
+      gmtl::ignore_unused_variable_warning(t);
+      TRANS_TYPE temporary;
+      return setTrans( temporary, arg );
+   }
+
+   /** Create a rotation datatype that will xform first vector to the second.
+    *  @pre  each vec needs to be normalized.
+    *  @post This function returns a temporary object.
+    */
+   template< typename ROTATION_TYPE >
+   inline ROTATION_TYPE makeRot( const Vec<typename ROTATION_TYPE::DataType, 3>& from,
+                                 const Vec<typename ROTATION_TYPE::DataType, 3>& to )
+   {
+      ROTATION_TYPE temporary;
+      return setRot( temporary, from, to );
+   }
+
+   /** set a rotation datatype that will xform first vector to the second.
+    *  @pre  each vec needs to be normalized.
+    *  @post generate rotation datatype that is the rotation between the vectors.
+    *  @note: only sets the rotation component of result, if result is a matrix, only sets the 3x3.
+    */
+   template <typename DEST_TYPE, typename DATA_TYPE>
+   inline DEST_TYPE& setRot( DEST_TYPE& result, const Vec<DATA_TYPE, 3>& from, const Vec<DATA_TYPE, 3>& to )
+   {
+      // @todo should assert that DEST_TYPE::DataType == DATA_TYPE
+      const DATA_TYPE epsilon = (DATA_TYPE)0.00001;
+
+      gmtlASSERT( gmtl::Math::isEqual( gmtl::length( from ), (DATA_TYPE)1.0, epsilon ) &&
+                  gmtl::Math::isEqual( gmtl::length( to ), (DATA_TYPE)1.0, epsilon ) /* &&
+                  "input params not normalized" */);
+
+      DATA_TYPE cosangle = dot( from, to );
+
+      // if cosangle is close to 1, so the vectors are close to being coincident
+      // Need to generate an angle of zero with any vector we like
+      // We'll choose identity (no rotation)
+      if ( Math::isEqual( cosangle, (DATA_TYPE)1.0, epsilon ) )
+      {
+         return result = DEST_TYPE();
+      }
+
+      // vectors are close to being opposite, so rotate one a little...
+      else if ( Math::isEqual( cosangle, (DATA_TYPE)-1.0, epsilon ) )
+      {
+         Vec<DATA_TYPE, 3> to_rot( to[0] + (DATA_TYPE)0.3, to[1] - (DATA_TYPE)0.15, to[2] - (DATA_TYPE)0.15 ), axis;
+         normalize( cross( axis, from, to_rot ) ); // setRot requires normalized vec
+         DATA_TYPE angle = Math::aCos( cosangle );
+         return setRot( result, gmtl::AxisAngle<DATA_TYPE>( angle, axis ) );
+      }
+
+      // This is the usual situation - take a cross-product of vec1 and vec2
+      // and that is the axis around which to rotate.
+      else
+      {
+         Vec<DATA_TYPE, 3> axis;
+         normalize( cross( axis, from, to ) ); // setRot requires normalized vec
+         DATA_TYPE angle = Math::aCos( cosangle );
+         return setRot( result, gmtl::AxisAngle<DATA_TYPE>( angle, axis ) );
+      }
+   }
+
+   /** @} */
+
+   /** Accesses a particular row in the matrix by copying the values in the row
+    * into the given vector.
+    *
+    * @param dest       the vector in which the values of the row will be placed
+    * @param src        the matrix being accessed
+    * @param row        the row of the matrix to access
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   void setRow(Vec<DATA_TYPE, COLS>& dest, const Matrix<DATA_TYPE, ROWS, COLS>& src, unsigned row)
+   {
+      for (unsigned i=0; i<COLS; ++i)
+      {
+         dest[i] = src[row][i];
+      }
+   }
+
+   /** Accesses a particular row in the matrix by creating a new vector
+    * containing the values in the given matrix.
+    *
+    * @param src        the matrix being accessed
+    * @param row        the row of the matrix to access
+    *
+    * @return  a vector containing the values in the requested row
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   Vec<DATA_TYPE, COLS> makeRow(const Matrix<DATA_TYPE, ROWS, COLS>& src, unsigned row)
+   {
+      Vec<DATA_TYPE, COLS> result;
+      setRow(result, src, row);
+      return result;
+   }
+
+   /** Accesses a particular column in the matrix by copying the values in the
+    * column into the given vector.
+    *
+    * @param dest       the vector in which the values of the column will be placed
+    * @param src        the matrix being accessed
+    * @param col        the column of the matrix to access
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   void setColumn(Vec<DATA_TYPE, ROWS>& dest, const Matrix<DATA_TYPE, ROWS, COLS>& src, unsigned col)
+   {
+      for (unsigned i=0; i<ROWS; ++i)
+      {
+         dest[i] = src[i][col];
+      }
+   }
+
+   /** Accesses a particular column in the matrix by creating a new vector
+    * containing the values in the given matrix.
+    *
+    * @param src        the matrix being accessed
+    * @param col        the column of the matrix to access
+    *
+    * @return  a vector containing the values in the requested column
+    */
+   template< typename DATA_TYPE, unsigned ROWS, unsigned COLS >
+   Vec<DATA_TYPE, ROWS> makeColumn(const Matrix<DATA_TYPE, ROWS, COLS>& src, unsigned col)
+   {
+      Vec<DATA_TYPE, ROWS> result;
+      setColumn(result, src, col);
+      return result;
+   }
+
+} // end gmtl namespace.
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Helpers.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Helpers.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Helpers.h	(revision 4)
@@ -0,0 +1,77 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Helpers.h,v
+ * Date modified: 2004/09/16 19:40:35
+ * Version:       1.2
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_HELPERS_H_
+#define _GMTL_HELPERS_H_
+
+#include <gmtl/Config.h>
+
+// Helper classes
+namespace gmtl
+{
+namespace helpers
+{
+
+struct ConstructorCounter
+{
+   unsigned mCount;
+
+   ConstructorCounter()
+   { mCount = 0; }
+
+   void inc()
+   { mCount += 1; }
+   unsigned get()
+   { return mCount; }
+};
+
+// Global version of the contructor counters
+//#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+
+//ConstructorCounter VecConstructCounter;   // Counter for vec objects
+inline ConstructorCounter* VecCtrCounterInstance()
+{
+   static ConstructorCounter vec_counter;
+   return &vec_counter;
+}
+
+//#endif
+
+
+}
+}
+
+#endif
+
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Intersection.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Intersection.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Intersection.h	(revision 4)
@@ -0,0 +1,873 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Intersection.h,v
+ * Date modified: 2006/06/08 21:11:59
+ * Version:       1.25
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_INTERSECTION_H_
+#define _GMTL_INTERSECTION_H_
+
+#include <algorithm>
+#include <limits>
+#include <gmtl/AABox.h>
+#include <gmtl/Point.h>
+#include <gmtl/Sphere.h>
+#include <gmtl/Vec.h>
+#include <gmtl/Plane.h>
+#include <gmtl/VecOps.h>
+#include <gmtl/Math.h>
+#include <gmtl/Ray.h>
+#include <gmtl/LineSeg.h>
+#include <gmtl/Tri.h>
+#include <gmtl/PlaneOps.h>
+
+namespace gmtl
+{
+   /**
+    * Tests if the given AABoxes intersect with each other. Sharing an edge IS
+    * considered intersection by this algorithm.
+    *
+    * @param box1    the first AA box to test
+    * @param box2    the second AA box to test
+    *
+    * @return  true if the boxes intersect; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect(const AABox<DATA_TYPE>& box1, const AABox<DATA_TYPE>& box2)
+   {
+      // Look for a separating axis on each box for each axis
+      if (box1.getMin()[0] > box2.getMax()[0])  return false;
+      if (box1.getMin()[1] > box2.getMax()[1])  return false;
+      if (box1.getMin()[2] > box2.getMax()[2])  return false;
+
+      if (box2.getMin()[0] > box1.getMax()[0])  return false;
+      if (box2.getMin()[1] > box1.getMax()[1])  return false;
+      if (box2.getMin()[2] > box1.getMax()[2])  return false;
+
+      // No separating axis ... they must intersect
+      return true;
+   }
+
+   /**
+    * Tests if the given AABox and point intersect with each other. On an edge IS
+    * considered intersection by this algorithm.
+    *
+    * @param box    the box to test
+    * @param point  the point to test
+    *
+    * @return  true if the point is within the box's bounds; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect( const AABox<DATA_TYPE>& box, const Point<DATA_TYPE, 3>& point )
+   {
+      // Look for a separating axis on each box for each axis
+      if (box.getMin()[0] > point[0])  return false;
+      if (box.getMin()[1] > point[1])  return false;
+      if (box.getMin()[2] > point[2])  return false;
+
+      if (point[0] > box.getMax()[0])  return false;
+      if (point[1] > box.getMax()[1])  return false;
+      if (point[2] > box.getMax()[2])  return false;
+
+      // they must intersect
+      return true;
+   }
+
+   /**
+    * Tests if the given AABoxes intersect if moved along the given paths. Using
+    * the AABox sweep test, the normalized time of the first and last points of
+    * contact are found.
+    *
+    * @param box1          the first box to test
+    * @param path1         the path the first box should travel along
+    * @param box2          the second box to test
+    * @param path2         the path the second box should travel along
+    * @param firstContact  set to the normalized time of the first point of contact
+    * @param secondContact set to the normalized time of the second point of contact
+    *
+    * @return  true if the boxes intersect at any time; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect( const AABox<DATA_TYPE>& box1, const Vec<DATA_TYPE, 3>& path1,
+                   const AABox<DATA_TYPE>& box2, const Vec<DATA_TYPE, 3>& path2,
+                   DATA_TYPE& firstContact, DATA_TYPE& secondContact )
+   {
+      // Algorithm taken from Gamasutra's article, "Simple Intersection Test for
+      // Games" - http://www.gamasutra.com/features/19991018/Gomez_3.htm
+      //
+      // This algorithm is solved from the frame of reference of box1
+
+      // Get the relative path (in normalized time)
+      Vec<DATA_TYPE, 3> path = path2 - path1;
+
+      // The first time of overlap along each axis
+      Vec<DATA_TYPE, 3> overlap1(DATA_TYPE(0), DATA_TYPE(0), DATA_TYPE(0));
+
+      // The second time of overlap along each axis
+      Vec<DATA_TYPE, 3> overlap2(DATA_TYPE(1), DATA_TYPE(1), DATA_TYPE(1));
+
+      // Check if the boxes already overlap
+      if (gmtl::intersect(box1, box2))
+      {
+         firstContact = secondContact = DATA_TYPE(0);
+         return true;
+      }
+
+      // Find the possible first and last times of overlap along each axis
+      for (int i=0; i<3; ++i)
+      {
+         if ((box1.getMax()[i] < box2.getMin()[i]) && (path[i] < DATA_TYPE(0)))
+         {
+            overlap1[i] = (box1.getMax()[i] - box2.getMin()[i]) / path[i];
+         }
+         else if ((box2.getMax()[i] < box1.getMin()[i]) && (path[i] > DATA_TYPE(0)))
+         {
+            overlap1[i] = (box1.getMin()[i] - box2.getMax()[i]) / path[i];
+         }
+
+         if ((box2.getMax()[i] > box1.getMin()[i]) && (path[i] < DATA_TYPE(0)))
+         {
+            overlap2[i] = (box1.getMin()[i] - box2.getMax()[i]) / path[i];
+         }
+         else if ((box1.getMax()[i] > box2.getMin()[i]) && (path[i] > DATA_TYPE(0)))
+         {
+            overlap2[i] = (box1.getMax()[i] - box2.getMin()[i]) / path[i];
+         }
+      }
+
+      // Calculate the first time of overlap
+      firstContact = Math::Max(overlap1[0], overlap1[1], overlap1[2]);
+
+      // Calculate the second time of overlap
+      secondContact = Math::Min(overlap2[0], overlap2[1], overlap2[2]);
+
+      // There could only have been a collision if the first overlap time
+      // occurred before the second overlap time
+      return firstContact <= secondContact;
+   }
+
+   /**
+    * Given an axis-aligned bounding box and a ray (or subclass thereof),
+    * returns whether the ray intersects the box, and if so, \p tIn and
+    * \p tOut are set to the parametric terms on the ray where the segment
+    * enters and exits the box respectively.
+    *
+    * The implementation of this function comes from the book
+    * <i>Geometric Tools for Computer Graphics</i>, pages 626-630.
+    *
+    * @note Internal function for performing an intersection test between an
+    *       axis-aligned bounding box and a ray. User code should not call this
+    *       function directly. It is used to capture the common code between
+    *       the gmtl::Ray<T> and gmtl::LineSeg<T> overloads of
+    *       gmtl::intersect() when intersecting with a gmtl::AABox<T>.
+    */
+   template<class DATA_TYPE>
+   bool intersectAABoxRay(const AABox<DATA_TYPE>& box,
+                          const Ray<DATA_TYPE>& ray, DATA_TYPE& tIn,
+                          DATA_TYPE& tOut)
+   {
+      tIn  = -std::numeric_limits<DATA_TYPE>::max();
+      tOut = std::numeric_limits<DATA_TYPE>::max();
+      DATA_TYPE t0, t1;
+      const DATA_TYPE epsilon(0.0000001);
+
+      // YZ plane.
+      if ( gmtl::Math::abs(ray.mDir[0]) < epsilon )
+      {
+         // Ray parallel to plane.
+         if ( ray.mOrigin[0] < box.mMin[0] || ray.mOrigin[0] > box.mMax[0] )
+         {
+            return false;
+         }
+      }
+
+      // XZ plane.
+      if ( gmtl::Math::abs(ray.mDir[1]) < epsilon )
+      {
+         // Ray parallel to plane.
+         if ( ray.mOrigin[1] < box.mMin[1] || ray.mOrigin[1] > box.mMax[1] )
+         {
+            return false;
+         }
+      }
+
+      // XY plane.
+      if ( gmtl::Math::abs(ray.mDir[2]) < epsilon )
+      {
+         // Ray parallel to plane.
+         if ( ray.mOrigin[2] < box.mMin[2] || ray.mOrigin[2] > box.mMax[2] )
+         {
+            return false;
+         }
+      }
+
+      // YZ plane.
+      t0 = (box.mMin[0] - ray.mOrigin[0]) / ray.mDir[0];
+      t1 = (box.mMax[0] - ray.mOrigin[0]) / ray.mDir[0];
+
+      if ( t0 > t1 )
+      {
+         std::swap(t0, t1);
+      }
+
+      if ( t0 > tIn )
+      {
+         tIn = t0;
+      }
+      if ( t1 < tOut )
+      {
+         tOut = t1;
+      }
+
+      if ( tIn > tOut || tOut < DATA_TYPE(0) )
+      {
+         return false;
+      }
+
+      // XZ plane.
+      t0 = (box.mMin[1] - ray.mOrigin[1]) / ray.mDir[1];
+      t1 = (box.mMax[1] - ray.mOrigin[1]) / ray.mDir[1];
+
+      if ( t0 > t1 )
+      {
+         std::swap(t0, t1);
+      }
+
+      if ( t0 > tIn )
+      {
+         tIn = t0;
+      }
+      if ( t1 < tOut )
+      {
+         tOut = t1;
+      }
+
+      if ( tIn > tOut || tOut < DATA_TYPE(0) )
+      {
+         return false;
+      }
+
+      // XY plane.
+      t0 = (box.mMin[2] - ray.mOrigin[2]) / ray.mDir[2];
+      t1 = (box.mMax[2] - ray.mOrigin[2]) / ray.mDir[2];
+
+      if ( t0 > t1 )
+      {
+         std::swap(t0, t1);
+      }
+
+      if ( t0 > tIn )
+      {
+         tIn = t0;
+      }
+      if ( t1 < tOut )
+      {
+         tOut = t1;
+      }
+
+      if ( tIn > tOut || tOut < DATA_TYPE(0) )
+      {
+         return false;
+      }
+
+      return true;
+   }
+
+   /**
+    * Given a line segment and an axis-aligned bounding box, returns whether
+    * the line intersects the box, and if so, \p tIn and \p tOut are set to
+    * the parametric terms on the line segment where the segment enters and
+    * exits the box respectively.
+    *
+    * @since 0.4.11
+    */
+   template<class DATA_TYPE>
+   bool intersect(const AABox<DATA_TYPE>& box, const LineSeg<DATA_TYPE>& seg,
+                  unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
+   {
+      numHits = 0;
+      bool result = intersectAABoxRay(box, seg, tIn, tOut);
+
+      if ( result )
+      {
+         // If tIn is less than 0, then the origin of the line segment is
+         // inside the bounding box (not on an edge)but the endpoint is
+         // outside.
+         if ( tIn < DATA_TYPE(0) )
+         {
+            numHits = 1;
+            tIn = tOut;
+         }
+         // If tIn is less than 0, then the origin of the line segment is
+         // outside the bounding box but the endpoint is inside (not on an
+         // edge).
+         else if ( tOut > DATA_TYPE(1) )
+         {
+            numHits = 1;
+            tOut = tIn;
+         }
+         // Otherwise, the line segement intersects the bounding box in two
+         // places. tIn and tOut reflect those points of intersection.
+         else
+         {
+            numHits = 2;
+         }
+      }
+
+      return result;
+   }
+
+   /**
+    * Given a line segment and an axis-aligned bounding box, returns whether
+    * the line intersects the box, and if so, \p tIn and \p tOut are set to
+    * the parametric terms on the line segment where the segment enters and
+    * exits the box respectively.
+    *
+    * @since 0.4.11
+    */
+   template<class DATA_TYPE>
+   bool intersect(const LineSeg<DATA_TYPE>& seg, const AABox<DATA_TYPE>& box,
+                  unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
+   {
+      return intersect(box, seg, numHits, tIn, tOut);
+   }
+
+   /**
+    * Given a ray and an axis-aligned bounding box, returns whether the ray
+    * intersects the box, and if so, \p tIn and \p tOut are set to the
+    * parametric terms on the ray where it enters and exits the box
+    * respectively.
+    *
+    * @since 0.4.11
+    */
+   template<class DATA_TYPE>
+   bool intersect(const AABox<DATA_TYPE>& box, const Ray<DATA_TYPE>& ray,
+                  unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
+   {
+      numHits = 0;
+
+      bool result = intersectAABoxRay(box, ray, tIn, tOut);
+
+      if ( result )
+      {
+         // Ray is inside the box.
+         if ( tIn < DATA_TYPE(0) )
+         {
+            tIn = tOut;
+            numHits = 1;
+         }
+         else
+         {
+            numHits = 2;
+         }
+      }
+
+      return result;
+   }
+
+   /**
+    * Given a ray and an axis-aligned bounding box, returns whether the ray
+    * intersects the box, and if so, \p tIn and \p tOut are set to the
+    * parametric terms on the ray where it enters and exits the box
+    * respectively.
+    *
+    * @since 0.4.11
+    */
+   template<class DATA_TYPE>
+   bool intersect(const Ray<DATA_TYPE>& ray, const AABox<DATA_TYPE>& box,
+                  unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
+   {
+      return intersect(box, ray, numHits, tIn, tOut);
+   }
+
+   /**
+    * Tests if the given Spheres intersect if moved along the given paths. Using
+    * the Sphere sweep test, the normalized time of the first and last points of
+    * contact are found.
+    *
+    * @param sph1          the first sphere to test
+    * @param path1         the path the first sphere should travel along
+    * @param sph2          the second sphere to test
+    * @param path2         the path the second sphere should travel along
+    * @param firstContact  set to the normalized time of the first point of contact
+    * @param secondContact set to the normalized time of the second point of contact
+    *
+    * @return  true if the spheres intersect; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect(const Sphere<DATA_TYPE>& sph1, const Vec<DATA_TYPE, 3>& path1,
+                  const Sphere<DATA_TYPE>& sph2, const Vec<DATA_TYPE, 3>& path2,
+                  DATA_TYPE& firstContact, DATA_TYPE& secondContact)
+   {
+      // Algorithm taken from Gamasutra's article, "Simple Intersection Test for
+      // Games" - http://www.gamasutra.com/features/19991018/Gomez_2.htm
+      //
+      // This algorithm is solved from the frame of reference of sph1
+
+      // Get the relative path (in normalized time)
+      const Vec<DATA_TYPE, 3> path = path2 - path1;
+
+      // Get the vector from sph1's starting point to sph2's starting point
+      const Vec<DATA_TYPE, 3> start_offset = sph2.getCenter() - sph1.getCenter();
+
+      // Compute the sum of the radii
+      const DATA_TYPE radius_sum = sph1.getRadius() + sph2.getRadius();
+
+      // u*u coefficient
+      const DATA_TYPE a = dot(path, path);
+
+      // u coefficient
+      const DATA_TYPE b = DATA_TYPE(2) * dot(path, start_offset);
+
+      // constant term
+      const DATA_TYPE c = dot(start_offset, start_offset) - radius_sum * radius_sum;
+
+      // Check if they're already overlapping
+      if (dot(start_offset, start_offset) <= radius_sum * radius_sum)
+      {
+         firstContact = secondContact = DATA_TYPE(0);
+         return true;
+      }
+
+      // Find the first and last points of intersection
+      if (Math::quadraticFormula(firstContact, secondContact, a, b, c))
+      {
+         // Swap first and second contacts if necessary
+         if (firstContact > secondContact)
+         {
+            std::swap(firstContact, secondContact);
+            return true;
+         }
+      }
+
+      return false;
+   }
+
+   /**
+    * Tests if the given AABox and Sphere intersect with each other. On an edge
+    * IS considered intersection by this algorithm.
+    *
+    * @param box  the box to test
+    * @param sph  the sphere to test
+    *
+    * @return  true if the items intersect; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect(const AABox<DATA_TYPE>& box, const Sphere<DATA_TYPE>& sph)
+   {
+      DATA_TYPE dist_sqr = DATA_TYPE(0);
+
+      // Compute the square of the distance from the sphere to the box
+      for (int i=0; i<3; ++i)
+      {
+         if (sph.getCenter()[i] < box.getMin()[i])
+         {
+            DATA_TYPE s = sph.getCenter()[i] - box.getMin()[i];
+            dist_sqr += s*s;
+         }
+         else if (sph.getCenter()[i] > box.getMax()[i])
+         {
+            DATA_TYPE s = sph.getCenter()[i] - box.getMax()[i];
+            dist_sqr += s*s;
+         }
+      }
+
+      return dist_sqr <= (sph.getRadius()*sph.getRadius());
+   }
+
+   /**
+    * Tests if the given AABox and Sphere intersect with each other. On an edge
+    * IS considered intersection by this algorithm.
+    *
+    * @param sph  the sphere to test
+    * @param box  the box to test
+    *
+    * @return  true if the items intersect; false otherwise
+    */
+   template<class DATA_TYPE>
+   bool intersect(const Sphere<DATA_TYPE>& sph, const AABox<DATA_TYPE>& box)
+   {
+      return gmtl::intersect(box, sph);
+   }
+
+   /**
+    * intersect point/sphere.
+    * @param point   the point to test
+    * @param sphere  the sphere to test
+    * @return true if point is in or on sphere
+    */
+   template<class DATA_TYPE>
+   bool intersect( const Sphere<DATA_TYPE>& sphere, const Point<DATA_TYPE, 3>& point )
+   {
+      gmtl::Vec<DATA_TYPE, 3> offset = point - sphere.getCenter();
+      DATA_TYPE dist = lengthSquared( offset ) - sphere.getRadius() * sphere.getRadius();
+
+      // point is inside the sphere when true
+      return  dist <= 0;
+   }
+
+   /**
+    * intersect ray/sphere-shell (not volume).
+    * only register hits with the surface of the sphere.
+    * note: after calling this, you can find the intersection point with: ray.getOrigin() + ray.getDir() * t
+    *
+    * @param ray     the ray to test
+    * @param sphere  the sphere to test
+    * @return returns intersection point in t, and the number of hits
+    * @return numhits, t0, t1 are undefined if return value is false
+    */
+   template<typename T>
+   inline bool intersect( const Sphere<T>& sphere, const Ray<T>& ray, int& numhits, float& t0, float& t1 )
+   {
+      numhits = -1;
+
+      // set up quadratic Q(t) = a*t^2 + 2*b*t + c
+      const Vec<T, 3> offset = ray.getOrigin() - sphere.getCenter();
+      const T a = lengthSquared( ray.getDir() );
+      const T b = dot( offset, ray.getDir() );
+      const T c = lengthSquared( offset ) - sphere.getRadius() * sphere.getRadius();
+
+
+
+      // no intersection if Q(t) has no real roots
+      const T discriminant = b * b - a * c;
+      if (discriminant < 0.0f)
+      {
+         numhits = 0;
+         return false;
+      }
+      else if (discriminant > 0.0f)
+      {
+         T root = Math::sqrt( discriminant );
+         T invA = T(1) / a;
+         t0 = (-b - root) * invA;
+         t1 = (-b + root) * invA;
+
+         // assert: t0 < t1 since A > 0
+
+         if (t0 >= T(0))
+         {
+            numhits = 2;
+            return true;
+         }
+         else if (t1 >= T(0))
+         {
+            numhits = 1;
+            t0 = t1;
+            return true;
+         }
+         else
+         {
+            numhits = 0;
+            return false;
+         }
+      }
+      else
+      {
+         t0 = -b / a;
+         if (t0 >= T(0))
+         {
+            numhits = 1;
+            return true;
+         }
+         else
+         {
+            numhits = 0;
+            return false;
+         }
+      }
+   }
+
+   /** intersect LineSeg/Sphere-shell (not volume).
+    * does intersection on sphere surface, point inside sphere doesn't count as an intersection
+    * returns intersection point(s) in t
+    * find intersection point(s) with: ray.getOrigin() + ray.getDir() * t
+    * numhits, t0, t1 are undefined if return value is false
+    */
+   template<typename T>
+   inline bool intersect( const Sphere<T>& sphere, const LineSeg<T>& lineseg, int& numhits, float& t0, float& t1 )
+   {
+      if (intersect( sphere, Ray<T>( lineseg ), numhits, t0, t1 ))
+      {
+         // throw out hits that are past 1 in segspace (off the end of the lineseg)
+         while (0 < numhits && 1.0f < t0)
+         {
+            --numhits;
+            t0 = t1;
+         }
+         if (2 == numhits && 1.0f < t1)
+         {
+            --numhits;
+         }
+         return 0 < numhits;
+      }
+      else
+      {
+         return false;
+      }
+   }
+
+   /**
+    * intersect lineseg/sphere-volume.
+    * register hits with both the surface and when end points land on the interior of the sphere.
+    * note: after calling this, you can find the intersection point with: ray.getOrigin() + ray.getDir() * t
+    *
+    * @param ray     the lineseg to test
+    * @param sphere  the sphere to test
+    * @return returns intersection point in t, and the number of hits
+    * @return numhits, t0, t1 are undefined if return value is false
+    */
+   template<typename T>
+   inline bool intersectVolume( const Sphere<T>& sphere, const LineSeg<T>& ray, int& numhits, float& t0, float& t1 )
+   {
+      bool result = intersect( sphere, ray, numhits, t0, t1 );
+      if (result && numhits == 2)
+      {
+         return true;
+      }
+      // todo: make this faster (find an early out) since 1 or 0 hits is the common case.
+      // volume test has some additional checks before we can throw it out because
+      // one of both points may be inside the volume, so we want to return hits for those as well...
+      else // 1 or 0 hits.
+      {
+         const T rsq = sphere.getRadius() * sphere.getRadius();
+         const Vec<T, 3> dist = ray.getOrigin() - sphere.getCenter();
+         const T a = lengthSquared( dist ) - rsq;
+         const T b = lengthSquared( gmtl::Vec<T,3>(dist + ray.getDir()) ) - rsq;
+
+         bool inside1 = a <= T( 0 );
+         bool inside2 = b <= T( 0 );
+
+         // one point is inside
+         if (numhits == 1 && inside1 && !inside2)
+         {
+            t1 = t0;
+            t0 = T(0);
+            numhits = 2;
+            return true;
+         }
+         else if (numhits == 1 && !inside1 && inside2)
+         {
+            t1 = T(1);
+            numhits = 2;
+            return true;
+         }
+         // maybe both points are inside?
+         else if (inside1 && inside2) // 0 hits.
+         {
+            t0 = T(0);
+            t1 = T(1);
+            numhits = 2;
+            return true;
+         }
+      }
+      return result;
+   }
+
+   /**
+    * intersect ray/sphere-volume.
+    * register hits with both the surface and when the origin lands in the interior of the sphere.
+    * note: after calling this, you can find the intersection point with: ray.getOrigin() + ray.getDir() * t
+    *
+    * @param ray     the ray to test
+    * @param sphere  the sphere to test
+    * @return returns intersection point in t, and the number of hits
+    * @return numhits, t0, t1 are undefined if return value is false
+    */
+   template<typename T>
+   inline bool intersectVolume( const Sphere<T>& sphere, const Ray<T>& ray, int& numhits, float& t0, float& t1 )
+   {
+      bool result = intersect( sphere, ray, numhits, t0, t1 );
+      if (result && numhits == 2)
+      {
+         return true;
+      }
+      else
+      {
+         const T rsq = sphere.getRadius() * sphere.getRadius();
+         const Vec<T, 3> dist = ray.getOrigin() - sphere.getCenter();
+         const T a = lengthSquared( dist ) - rsq;
+
+         bool inside = a <= T( 0 );
+
+         // start point is inside
+         if (inside)
+         {
+            t1 = t0;
+            t0 = T(0);
+            numhits = 2;
+            return true;
+         }
+      }
+      return result;
+   }
+
+   /**
+    * Tests if the given plane and ray intersect with each other.
+    *
+    *  @param ray - the Ray
+    *  @param plane - the Plane
+    *  @param t - t gives you the intersection point:
+    *         isect_point = ray.origin + ray.dir * t
+    *
+    *  @return true if the ray intersects the plane.
+    *  @note If ray is parallel to plane: t=0, ret:true -> on plane, ret:false -> No hit
+    */
+   template<class DATA_TYPE>
+   bool intersect( const Plane<DATA_TYPE>& plane, const Ray<DATA_TYPE>& ray, DATA_TYPE& t )
+   {
+      const float eps(0.00001f);
+
+      // t = -(n·P + d)
+      Vec<DATA_TYPE, 3> N( plane.getNormal() );
+      float denom( dot(N,ray.getDir()) );
+      if(gmtl::Math::abs(denom) < eps)    // Ray parallel to plane
+      {
+         t = 0;
+         if(distance(plane, ray.mOrigin) < eps)     // Test for ray on plane
+         { return true; }
+         else
+         { return false; }
+      }
+      t = dot( N, Vec<DATA_TYPE,3>(N * plane.getOffset() - ray.getOrigin()) ) / denom;
+
+      return (DATA_TYPE)0 <= t;
+   }
+
+   /**
+    * Tests if the given plane and lineseg intersect with each other.
+    *
+    *  @param ray - the lineseg
+    *  @param plane - the Plane
+    *  @param t - t gives you the intersection point:
+    *         isect_point = lineseg.origin + lineseg.dir * t
+    *
+    *  @return true if the lineseg intersects the plane.
+    */
+   template<class DATA_TYPE>
+   bool intersect( const Plane<DATA_TYPE>& plane, const LineSeg<DATA_TYPE>& seg, DATA_TYPE& t )
+   {
+      bool res(intersect(plane, static_cast<Ray<DATA_TYPE> >(seg), t));
+      return res && t <= (DATA_TYPE)1.0;
+   }
+
+   /**
+    * Tests if the given triangle and ray intersect with each other.
+    *
+    *  @param tri - the triangle (ccw ordering)
+    *  @param ray - the ray
+    *  @param u,v - tangent space u/v coordinates of the intersection
+    *  @param t - an indicator of the intersection location
+    *  @post t gives you the intersection point:
+    *         isect = ray.dir * t + ray.origin
+    *  @return true if the ray intersects the triangle.
+    *  @see from http://www.acm.org/jgt/papers/MollerTrumbore97/code.html
+    */
+   template<class DATA_TYPE>
+   bool intersect( const Tri<DATA_TYPE>& tri, const Ray<DATA_TYPE>& ray,
+                        float& u, float& v, float& t )
+   {
+      const float EPSILON = (DATA_TYPE)0.00001f;
+      Vec<DATA_TYPE, 3> edge1, edge2, tvec, pvec, qvec;
+      float det,inv_det;
+
+      /* find vectors for two edges sharing vert0 */
+      edge1 = tri[1] - tri[0];
+      edge2 = tri[2] - tri[0];
+
+      /* begin calculating determinant - also used to calculate U parameter */
+      gmtl::cross( pvec, ray.getDir(), edge2 );
+
+      /* if determinant is near zero, ray lies in plane of triangle */
+      det = gmtl::dot( edge1, pvec );
+
+      if (det < EPSILON)
+         return false;
+
+      /* calculate distance from vert0 to ray origin */
+      tvec = ray.getOrigin() - tri[0];
+
+      /* calculate U parameter and test bounds */
+      u = gmtl::dot( tvec, pvec );
+      if (u < 0.0 || u > det)
+         return false;
+
+      /* prepare to test V parameter */
+      gmtl::cross( qvec, tvec, edge1 );
+
+      /* calculate V parameter and test bounds */
+      v = gmtl::dot( ray.getDir(), qvec );
+      if (v < 0.0 || u + v > det)
+         return false;
+
+      /* calculate t, scale parameters, ray intersects triangle */
+      t = gmtl::dot( edge2, qvec );
+      inv_det = ((DATA_TYPE)1.0) / det;
+      t *= inv_det;
+      u *= inv_det;
+      v *= inv_det;
+
+      // test if t is within the ray boundary (when t >= 0)
+      return t >= (DATA_TYPE)0;
+   }
+
+   /**
+    * Tests if the given triangle and line segment intersect with each other.
+    *
+    *  @param tri - the triangle (ccw ordering)
+    *  @param lineseg - the line segment
+    *  @param u,v - tangent space u/v coordinates of the intersection
+    *  @param t - an indicator of the intersection point
+    *  @post t gives you the intersection point:
+    *         isect = lineseg.getDir() * t + lineseg.getOrigin()
+    *
+    *  @return true if the line segment intersects the triangle.
+    */
+   template<class DATA_TYPE>
+   bool intersect( const Tri<DATA_TYPE>& tri, const LineSeg<DATA_TYPE>& lineseg,
+                        float& u, float& v, float& t )
+   {
+      const DATA_TYPE eps = (DATA_TYPE)0.0001010101;
+      DATA_TYPE l = length( lineseg.getDir() );
+      if (eps < l)
+      {
+         Ray<DATA_TYPE> temp( lineseg.getOrigin(), lineseg.getDir() );
+         bool result = intersect( tri, temp, u, v, t );
+         return result && t <= (DATA_TYPE)1.0;
+      }
+      else
+      {  return false; }
+   }
+}
+
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/LineSeg.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/LineSeg.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/LineSeg.h	(revision 4)
@@ -0,0 +1,115 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          LineSeg.h,v
+ * Date modified: 2003/03/03 00:54:05
+ * Version:       1.7
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_LINESEG_H_
+#define _GMTL_LINESEG_H_
+
+#include <gmtl/Point.h>
+#include <gmtl/Vec.h>
+#include <gmtl/VecOps.h>
+#include <gmtl/Ray.h>
+
+namespace gmtl {
+
+/**
+ * Describes a line segment. This is represented by a point origin O and a
+ * vector spanning the length of the line segement originating at O. Thus any
+ * point on the line segment can be described as
+ *
+ * P(s) = O + Vs
+ *
+ * where 0 <= s <= 1
+ *
+ * @param DATA_TYPE     the internal type used for the point and vector
+ */
+template <typename DATA_TYPE>
+class LineSeg : public Ray<DATA_TYPE>
+{
+public:
+   /**
+    * Constructs a line segment at the origin with a zero vector.
+    */
+   LineSeg()
+   {}
+
+   /**
+    * Constructs a line segment with the given origin and vector.
+    *
+    * @param origin     the point at which the line segment starts
+    * @param dir        the vector describing the direction and length of the
+    *                   line segment starting at origin
+    */
+   LineSeg( const Point<DATA_TYPE, 3>& origin, const Vec<DATA_TYPE, 3>& dir )
+      : Ray<DATA_TYPE>( origin, dir )
+   {}
+
+   /**
+    * Constructs an exact duplicate of the given line segment.
+    *
+    * @param ray    the line segment to copy
+    */
+   LineSeg( const LineSeg& ray ) : Ray<DATA_TYPE>( ray )
+   {
+   }
+
+   /**
+    * Constructs a line segment with the given beginning and ending points.
+    *
+    * @param beg     the point at the beginning of the line segment
+    * @param end     the point at the end of the line segment
+    */
+   LineSeg( const Point<DATA_TYPE, 3>& beg, const Point<DATA_TYPE, 3>& end )
+      : Ray<DATA_TYPE>()
+   {
+      this->mOrigin = beg;
+      this->mDir = end - beg;
+   }
+
+   /**
+    * Gets the length of this line segment.
+    * @return the length of the line segment
+    */
+   DATA_TYPE getLength() const
+   {
+      return length(this->mDir);
+   }
+};
+
+
+// --- helper types --- //
+typedef LineSeg<float>  LineSegf;
+typedef LineSeg<double> LineSegd;
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/LineSegOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/LineSegOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/LineSegOps.h	(revision 4)
@@ -0,0 +1,92 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          LineSegOps.h,v
+ * Date modified: 2004/09/16 21:21:09
+ * Version:       1.8
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_LINESEGOPS_H_
+#define _GMTL_LINESEGOPS_H_
+
+#include <gmtl/LineSeg.h>
+#include <gmtl/RayOps.h>
+
+namespace gmtl {
+
+/**
+ * Finds the closest point on the line segment to a given point.
+ *
+ * @param lineseg    the line segment to test
+ * @param pt         the point which to test against lineseg
+ *
+ * @return  the point on the line segment closest to pt
+ */
+template< class DATA_TYPE >
+Point<DATA_TYPE, 3> findNearestPt( const LineSeg<DATA_TYPE>& lineseg,
+                                   const Point<DATA_TYPE, 3>& pt )
+{
+   // result = origin + dir * dot((pt-origin), dir)
+   return ( lineseg.mOrigin + lineseg.mDir *
+            dot(pt - lineseg.mOrigin, lineseg.mDir) );
+}
+
+/**
+ * Computes the shortest distance from the line segment to the given point.
+ *
+ * @param lineseg    the line segment to test
+ * @param pt         the point which to test against lineseg
+ *
+ * @return  the shortest distance from pt to lineseg
+ */
+template< class DATA_TYPE >
+inline DATA_TYPE distance( const LineSeg<DATA_TYPE>& lineseg,
+                           const Point<DATA_TYPE, 3>& pt )
+{
+   return gmtl::length(gmtl::Vec<DATA_TYPE, 3>(pt - findNearestPt(lineseg, pt)));
+}
+
+/**
+ * Computes the shortest distance from the line segment to the given point.
+ *
+ * @param lineseg    the line segment to test
+ * @param pt         the point which to test against lineseg
+ *
+ * @return  the squared shortest distance from pt to lineseg (value is squared, this func is slightly faster since it doesn't involve a sqrt)
+ */
+template< class DATA_TYPE >
+inline DATA_TYPE distanceSquared( const LineSeg<DATA_TYPE>& lineseg,
+                           const Point<DATA_TYPE, 3>& pt )
+{
+   return gmtl::lengthSquared(gmtl::Vec<DATA_TYPE, 3>(pt - findNearestPt(lineseg, pt)));
+}
+
+
+} // namespace gmtl
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Math.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Math.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Math.h	(revision 4)
@@ -0,0 +1,614 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Math.h,v
+ * Date modified: 2005/06/23 21:13:28
+ * Version:       1.40
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_MATH_H_
+#define _GMTL_MATH_H_
+
+#include <math.h>
+#include <stdlib.h>
+#include <gmtl/Defines.h>
+#include <gmtl/Util/Assert.h>
+
+namespace gmtl
+{
+
+/** Base class for Rotation orders
+ *  @ingroup Defines
+ * @see XYZ, ZYX, ZXY
+ */
+struct RotationOrderBase { enum { IS_ROTORDER = 1 }; };
+
+/** XYZ Rotation order
+ *  @ingroup Defines */
+struct XYZ : public RotationOrderBase { enum { ID = 0 }; };
+
+/** ZYX Rotation order
+ *  @ingroup Defines */
+struct ZYX : public RotationOrderBase { enum { ID = 1 }; };
+
+/** ZXY Rotation order
+ *  @ingroup Defines */
+struct ZXY : public RotationOrderBase { enum { ID = 2 }; };
+
+namespace Math
+{
+   /** @ingroup Math
+    *  @name Mathematical constants
+    *  @{
+    */
+   const float TWO_PI = 6.28318530717958647692f;
+   const float PI = 3.14159265358979323846f; //3.14159265358979323846264338327950288419716939937510;
+   const float PI_OVER_2 = 1.57079632679489661923f;
+   const float PI_OVER_4 = 0.78539816339744830962f;
+   /** @} */
+
+   /** @ingroup Math
+    *  @name C Math Abstraction
+    *  @{
+    */
+//----------------------------------------------------------------------------
+template <typename T>
+inline T abs( T iValue )
+{
+    return T( iValue >= ((T)0) ? iValue : -iValue );
+}
+
+inline float abs(float iValue)
+{  return fabsf(iValue); }
+inline double abs(double iValue)
+{  return fabs(iValue); }
+inline int abs(int iValue)
+{  return ::abs(iValue); }
+inline long abs(long iValue)
+{  return labs(iValue); }
+
+//----------------------------------------------------------------------------
+template <typename T>
+inline T ceil( T fValue );
+inline float ceil( float fValue )
+{
+#ifdef NO_CEILF
+   return float(::ceil(fValue));
+#else
+   return float( ::ceilf( fValue ) );
+#endif
+}
+inline double ceil( double fValue )
+{
+    return double( ::ceil( fValue ) );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T floor( T fValue ); // why do a floor of int?  shouldn't compile...
+inline float floor( float fValue )
+{
+#ifdef NO_FLOORF
+   return float(::floor(fValue));
+#else
+   return float( ::floorf( fValue ) );
+#endif
+}
+inline double floor( double fValue )
+{
+    return double( ::floor( fValue ) );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline int sign( T iValue )
+{
+   if (iValue > T(0))
+   {
+      return 1;
+   }
+   else
+   {
+      if (iValue < T(0))
+      {
+         return -1;
+      }
+      else
+      {
+         return 0;
+      }
+   }
+}
+//----------------------------------------------------------------------------
+/**
+ * Clamps the given value down to zero if it is within epsilon of zero.
+ *
+ * @param value      the value to clamp
+ * @param eps        the epsilon tolerance or zero by default
+ *
+ * @return  zero if the value is close to 0, the value otherwise
+ */
+template <typename T>
+inline T zeroClamp( T value, T eps = T(0) )
+{
+   return ( (gmtl::Math::abs(value) <= eps) ? T(0) : value );
+}
+
+//----------------------------------------------------------------------------
+// don't allow non-float types, because their ret val wont be correct
+// i.e. with int, the int retval will be rounded up or down.
+//      we'd need a float retval to do it right, but we can't specialize by ret
+template <typename T>
+inline T aCos( T fValue );
+inline float aCos( float fValue )
+{
+    if ( -1.0f < fValue )
+    {
+        if ( fValue < 1.0f )
+        {
+#ifdef NO_ACOSF
+            return float(::acos(fValue));
+#else
+            return float( ::acosf( fValue ) );
+#endif
+        }
+        else
+            return 0.0f;
+    }
+    else
+    {
+        return (float)gmtl::Math::PI;
+    }
+}
+inline double aCos( double fValue )
+{
+    if ( -1.0 < fValue )
+    {
+        if ( fValue < 1.0 )
+            return double( ::acos( fValue ) );
+        else
+            return 0.0;
+    }
+    else
+    {
+        return (double)gmtl::Math::PI;
+    }
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T aSin( T fValue );
+inline float aSin( float fValue )
+{
+    if ( -1.0f < fValue )
+    {
+        if ( fValue < 1.0f )
+        {
+#ifdef NO_ASINF
+            return float(::asin(fValue));
+#else
+            return float( ::asinf( fValue ) );
+#endif
+        }
+        else
+            return (float)-gmtl::Math::PI_OVER_2;
+    }
+    else
+    {
+        return (float)gmtl::Math::PI_OVER_2;
+    }
+}
+inline double aSin( double fValue )
+{
+    if ( -1.0 < fValue )
+    {
+        if ( fValue < 1.0 )
+            return double( ::asin( fValue ) );
+        else
+            return (double)-gmtl::Math::PI_OVER_2;
+    }
+    else
+    {
+        return (double)gmtl::Math::PI_OVER_2;
+    }
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T aTan( T fValue );
+inline double aTan( double fValue )
+{
+    return ::atan( fValue );
+}
+inline float aTan( float fValue )
+{
+#ifdef NO_TANF
+   return float(::atan(fValue));
+#else
+   return float( ::atanf( fValue ) );
+#endif
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T aTan2( T fY, T fX );
+inline float aTan2( float fY, float fX )
+{
+#ifdef NO_ATAN2F
+   return float(::atan2(fY, fX));
+#else
+   return float( ::atan2f( fY, fX ) );
+#endif
+}
+inline double aTan2( double fY, double fX )
+{
+    return double( ::atan2( fY, fX ) );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T cos( T fValue );
+inline float cos( float fValue )
+{
+#ifdef NO_COSF
+   return float(::cos(fValue));
+#else
+   return float( ::cosf( fValue ) );
+#endif
+}
+inline double cos( double fValue )
+{
+    return double( ::cos( fValue ) );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T exp( T fValue );
+inline float exp( float fValue )
+{
+#ifdef NO_EXPF
+   return float(::exp(fValue));
+#else
+   return float( ::expf( fValue ) );
+#endif
+}
+inline double exp( double fValue )
+{
+    return double( ::exp( fValue ) );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T log( T fValue );
+inline double log( double fValue )
+{
+    return double( ::log( fValue ) );
+}
+inline float log( float fValue )
+{
+#ifdef NO_LOGF
+   return float(::log(fValue));
+#else
+   return float( ::logf( fValue ) );
+#endif
+}
+//----------------------------------------------------------------------------
+inline double pow( double fBase, double fExponent)
+{
+    return double( ::pow( fBase, fExponent ) );
+}
+inline float pow( float fBase, float fExponent)
+{
+#ifdef NO_POWF
+   return float(::pow(fBase, fExponent));
+#else
+   return float( ::powf( fBase, fExponent ) );
+#endif
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T sin( T fValue );
+inline double sin( double fValue )
+{
+    return double( ::sin( fValue ) );
+}
+inline float sin( float fValue )
+{
+#ifdef NO_SINF
+   return float(::sin(fValue));
+#else
+   return float( ::sinf( fValue ) );
+#endif
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T tan( T fValue );
+inline double tan( double fValue )
+{
+    return double( ::tan( fValue ) );
+}
+inline float tan( float fValue )
+{
+#ifdef NO_TANF
+   return float(::tan(fValue));
+#else
+   return float( ::tanf( fValue ) );
+#endif
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T sqr( T fValue )
+{
+    return T( fValue * fValue );
+}
+//----------------------------------------------------------------------------
+template <typename T>
+inline T sqrt( T fValue )
+{
+#ifdef NO_SQRTF
+   return T(::sqrt(((float)fValue)));
+#else
+   return T( ::sqrtf( ((float)fValue) ) );
+#endif
+}
+inline double sqrt( double fValue )
+{
+    return double( ::sqrt( fValue ) );
+}
+
+/** Fast inverse square root.
+ */
+inline float fastInvSqrt(float x)
+{
+   const float xhalf(0.5f*x);
+   long i = *(long*)&x;
+   i = 0x5f3759df - (i>>1);    // This hides a good amount of math
+   x = *(float*)&i;
+   x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
+   return x;
+}
+
+inline float fastInvSqrt2(float x)
+{
+   const float xhalf(0.5f*x);
+   long i = *(long*)&x;
+   i = 0x5f3759df - (i>>1);    // This hides a good amount of math
+   x = *(float*)&i;
+   x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
+   x = x*(1.5f - xhalf*x*x);
+   return x;
+}
+
+inline float fastInvSqrt3(float x)
+{
+   const float xhalf(0.5f*x);
+   long i = *(long*)&x;
+   i = 0x5f3759df - (i>>1);    // This hides a good amount of math
+   x = *(float*)&i;
+   x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
+   x = x*(1.5f - xhalf*x*x);
+   x = x*(1.5f - xhalf*x*x);
+   return x;
+}
+
+
+//----------------------------------------------------------------------------
+/**
+ * Seeds the pseudorandom number generator with the given seed.
+ *
+ * @param seed  the seed for the pseudorandom number generator.
+ */
+inline void seedRandom(unsigned int seed)
+{
+   ::srand(seed);
+}
+
+/** get a random number between 0 and 1
+ * @post returns number between 0 and 1
+ */
+inline float unitRandom()
+{
+   return float(::rand())/float(RAND_MAX);
+}
+
+/** return a random number between x1 and x2
+ * RETURNS: random number between x1 and x2
+ */
+inline float rangeRandom( float x1, float x2 )
+{
+   float r = gmtl::Math::unitRandom();
+   float size = x2 - x1;
+   return float( r * size + x1 );
+}
+
+/*
+float SymmetricRandom ()
+{
+    return 2.0*float(rand())/float(RAND_MAX) - 1.0;
+}
+*/
+//----------------------------------------------------------------------------
+
+inline float deg2Rad( float fVal )
+{
+   return float( fVal * (float)(gmtl::Math::PI/180.0) );
+}
+inline double deg2Rad( double fVal )
+{
+   return double( fVal * (double)(gmtl::Math::PI/180.0) );
+}
+
+inline float rad2Deg( float fVal )
+{
+   return float( fVal * (float)(180.0/gmtl::Math::PI) );
+}
+inline double rad2Deg( double fVal )
+{
+   return double( fVal * (double)(180.0/gmtl::Math::PI) );
+}
+//----------------------------------------------------------------------------
+
+/** Is almost equal?
+ * test for equality within some tolerance...
+ * @PRE: tolerance must be >= 0
+ */
+template <class T>
+inline bool isEqual( const T& a, const T& b, const T& tolerance )
+{
+   gmtlASSERT( tolerance >= (T)0 );
+   return bool( gmtl::Math::abs( a - b ) <= tolerance );
+}
+//----------------------------------------------------------------------------
+/** cut off the digits after the decimal place */
+template <class T>
+inline T trunc( T val )
+{
+   return T( (val < ((T)0)) ? gmtl::Math::ceil( val ) : gmtl::Math::floor( val ) );
+}
+/** round to nearest integer */
+template <class T>
+inline T round( T p )
+{
+   return T( gmtl::Math::floor( p + (T)0.5 ) );
+}
+//----------------------------------------------------------------------------
+/** min returns the minimum of 2 values */
+template <class T>
+inline T Min( const T& x, const T& y )
+{
+   return ( x > y ) ? y : x;
+}
+/** min returns the minimum of 3 values */
+template <class T>
+inline T Min( const T& x, const T& y, const T& z )
+{
+   return Min( gmtl::Math::Min( x, y ), z );
+}
+/** min returns the minimum of 4 values */
+template <class T>
+inline T Min( const T& w, const T& x, const T& y, const T& z )
+{
+   return gmtl::Math::Min( gmtl::Math::Min( w, x ), gmtl::Math::Min( y, z ) );
+}
+
+/** max returns the maximum of 2 values */
+template <class T>
+inline T Max( const T& x, const T& y )
+{
+   return ( x > y ) ? x : y;
+}
+/** max returns the maximum of 3 values */
+template <class T>
+inline T Max( const T& x, const T& y, const T& z )
+{
+   return Max( gmtl::Math::Max( x, y ), z );
+}
+/** max returns the maximum of 4 values */
+template <class T>
+inline T Max( const T& w, const T& x, const T& y, const T& z )
+{
+   return gmtl::Math::Max( gmtl::Math::Max( w, x ), gmtl::Math::Max( y, z ) );
+}
+//----------------------------------------------------------------------------
+/** Compute the factorial.
+ * give - an object who's type has operator++, operator=, operator<=, and operator*= defined.
+ *        it should be a single valued scalar type such as an int, float, double etc....
+ * NOTE: This could be faster with a lookup table, but then wouldn't work templated : kevin
+ */
+template<class T>
+inline T factorial(T rhs)
+{
+   T lhs = (T)1;
+
+   for( T x = (T)1; x <= rhs; ++x )
+   {
+      lhs *= x;
+   }
+
+   return lhs;
+}
+/** @} */
+
+/**
+ * clamp "number" to a range between lo and hi
+ */
+template <class T>
+inline T clamp( T number, T lo, T hi )
+{
+   if (number > hi) number = hi;
+   else if (number < lo) number = lo;
+   return number;
+}
+
+/** @ingroup Interp
+ * @name Scalar type interpolation (for doubles, floats, etc...)
+ * @{
+ */
+
+/** Linear Interpolation between number [a] and [b].
+ *  lerp=0.0 returns a, lerp=1.0 returns b
+ *  @pre use double or float only...
+ */
+template <class T, typename U>
+inline void lerp( T& result, const U& lerp, const T& a, const T& b )
+{
+    T size = b - a;
+    result = ((U)a) + (((U)size) * lerp);
+}
+/** @} */
+
+/**
+ * Uses the quadratic formula to compute the 2 roots of the given 2nd degree
+ * polynomial in the form of Ax^2 + Bx + C.
+ *
+ * @param r1   set to the first root
+ * @param r2   set to the second root
+ * @param a    the coefficient to x^2
+ * @param b    the coefficient to x^1
+ * @param c    the coefficient to x^0
+ *
+ * @return  true if both r1 and r2 are real; false otherwise
+ */
+template <class T>
+inline bool quadraticFormula(T& r1, T& r2, const T& a, const T& b, const T& c)
+{
+   const T q = b*b - T(4)*a*c;
+
+   // the result has real roots
+   if (q >= 0)
+   {
+      const T sq = gmtl::Math::sqrt(q);
+      const T d = T(1) / (T(2) * a);
+      r1 = (-b + sq) * d;
+      r2 = (-b - sq) * d;
+      return true;
+   }
+   // the result has complex roots
+   else
+   {
+      return false;
+   }
+}
+
+} // end namespace Math
+} // end namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Matrix.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Matrix.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Matrix.h	(revision 4)
@@ -0,0 +1,629 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Matrix.h,v
+ * Date modified: 2004/11/22 15:04:05
+ * Version:       1.39
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_MATRIX_H_
+#define _GMTL_MATRIX_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Math.h>
+#include <gmtl/Util/Assert.h>
+#include <gmtl/Util/StaticAssert.h>
+
+namespace gmtl
+{
+
+/**
+ * State tracked NxM dimensional Matrix (ordered in memory by Column)
+ *
+ * <b>Memory mapping:</b>
+ *
+ * gmtl::Matrix stores its elements in column major order.
+ * That is, it stores each column end-to-end in memory.
+ *
+ * Typically, for 3D transform matrices, the 3x3 rotation is
+ * in the first three columns, while the translation is in the last column.
+ *
+ * This memory alignment is chosen for compatibility with the OpenGL graphics
+ * API and others, which take matrices in this specific column major ordering
+ * described above.
+ *
+ * See the interfaces for operator[r][c] and operator(r,c) for how to iterate
+ * over columns and rows for a GMTL Matrix.
+ *
+ * <b>NOTES on Matrix memory layout and [][] accessors:</b>
+ * <ul>
+ * <li> gmtl Matrix memory is "column major" ordered, where columns are end
+ *      to end in memory, while a C/C++ Matrix accessed the same way
+ *      (using operator[][]) as a gmtl Matrix is "row major" ordered.
+ *
+ * <li> As a result, a gmtl matrix stores elements in memory transposed from
+ *      the equivelent matrix defined using an array in the C/C++
+ *      language, assuming they are accessed the same way (see example).
+ * <ul>
+ *    <li> Illustrative Example:                                           <br>
+ *         Given two flavors of matrix, C/C++, and gmtl:                   <br>
+ *             float cmat[n][m];   and    gmtl::Matrix<float, n, m> mat;   <br>
+ *         Writing values into each, while accessing them the same:        <br>
+ *             cmat[row][col] = mat[row][col] = some_values[x];            <br>
+ *         Then reading values from the matrix array:                      <br>
+ *             ((float*)cmat)   and    mat.getData()                       <br>
+ *         <i>Will yield pointers to memory containing matrices that are the transpose of each other.</i>
+ * </ul>
+ * <li> In practice, the differences between GMTL and C/C++ defined matrices
+ *      all depends how you iterate over your matrix.                                              <br>
+ *      If gmtl is accessed mat[row][col] and C/C++ is accessed mat[col][row], then
+ *      memory-wise, these two will yield the same memory mapping (column major as described above),
+ *      thus, are equivelent and can both be used interchangably in many popular graphics APIs
+ *      such as OpenGL, DirectX, and others.
+ *
+ * <li> In C/C++ access of a matrix via mat[row][col] yields this memory mapping after using ((float*)mat) to return it:<br>
+ *  <pre>
+ *    (0,0) (0,1) (0,2) (0,3)   <=== Contiguous memory arranged by row
+ *    (1,0) (1,1) (1,2) (1,3)   <=== Contiguous
+ *    (2,0) (2,1) (2,2) (2,3)   <=== Contiguous
+ *    (3,0) (3,1) (3,2) (3,3)   <=== Contiguous
+ *
+ *  or linearly if you prefer:
+ *    (0,0) (0,1) (0,2) (0,3) (1,0) (1,1) (1,2) (1,3) (2,0) (2,1) (2,2) (2,3) (3,0) (3,1) (3,2) (3,3)
+ *  </pre>
+ *
+ * <li> In gmtl, access of a matrix via mat[row][col] yields this memory mapping after using getData() to return it:<br>
+ *  <pre>
+ *    (0,0) (0,1) (0,2) (0,3)
+ *    (1,0) (1,1) (1,2) (1,3)
+ *    (2,0) (2,1) (2,2) (2,3)
+ *    (3,0) (3,1) (3,2) (3,3)
+ *      ^     ^     ^     ^
+ *    --1-----2-----3-----4---- Contiguous memory arranged by column
+ *
+ *  or linearly if you prefer:
+ *    (0,0) (1,0) (2,0) (3,0) (0,1) (1,1) (2,1) (3,1) (0,2) (1,2) (2,2) (3,2) (0,3) (1,3) (2,3) (3,3)
+ *  </pre>
+ * </ul>
+ *
+ * <b>State Tracking:</b>
+ *
+ * The idea of a state-tracked matrix is that if we track the information
+ * as it is stored into the matrix, then other operations could make more optimal
+ * descisions based on the known state.  A good example is in matrix invertion,
+ * a reletively costly operation for matrices.  However, if we know the matrix state
+ * is (i.e.) ORTHOGONAL, then inversion becomes a simple transpose operation.
+ * There are also optimizations with multiplication, as well as other.
+ *
+ * One side effect of this state tracking is that EVERY MATRIC FUNCTION NEEDS TO
+ * TRACK STATE.  This means that anyone writing custom methods, or extentions to
+ * gmtl, will need to pay close attention to matrix state.
+ *
+ * To facilitate state tracking in extensions, we've provided the function
+ * gmtl::combineMatrixStates() to help in determining state based on two
+ * combined matrices.
+ * @see Matrix44f
+ * @see Matrix44d
+ * @ingroup Types
+ */
+template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+class Matrix
+{
+public:
+   // This is a hack to work around a bug with GCC 3.3 on Mac OS X where
+   // boost::is_polymorphic returns a false positive.  The details can be
+   // found in the Boost.Python FAQ:
+   //    http://www.boost.org/libs/python/doc/v2/faq.html#macosx
+#if defined(__MACH__) && defined(__APPLE_CC__) && defined(__GNUC__) && \
+    __GNUC__ == 3 && __GNUC_MINOR__ == 3
+   bool dummy_;
+#endif
+
+   /** use this to declare single value types of the same type as this matrix.
+    */
+   typedef DATA_TYPE DataType;
+   enum Params
+   {
+      Rows = ROWS, Cols = COLS
+   };
+
+   /** Helper class for Matrix op[].
+   * This class encapsulates the row that the user is accessing
+   * and implements a new op[] that passes the column to use
+   */
+   class RowAccessor
+   {
+   public:
+      typedef DATA_TYPE DataType;
+
+      RowAccessor(Matrix<DATA_TYPE,ROWS,COLS>* mat, const unsigned row)
+         : mMat(mat), mRow(row)
+      {
+         gmtlASSERT(row < ROWS);
+         gmtlASSERT(NULL != mat);
+      }
+
+      DATA_TYPE& operator[](const unsigned column)
+      {
+         gmtlASSERT(column < COLS);
+         return (*mMat)(mRow,column);
+      }
+
+      Matrix<DATA_TYPE,ROWS,COLS>*  mMat;
+      unsigned                      mRow;    /** The row being accessed */
+   };
+
+   /** Helper class for Matrix op[] const.
+   * This class encapsulates the row that the user is accessing
+   * and implements a new op[] that passes the column to use
+   */
+   class ConstRowAccessor
+   {
+   public:
+      typedef DATA_TYPE DataType;
+
+      ConstRowAccessor( const Matrix<DATA_TYPE,ROWS,COLS>* mat,
+                        const unsigned row )
+         : mMat( mat ), mRow( row )
+      {
+         gmtlASSERT( row < ROWS );
+         gmtlASSERT( NULL != mat );
+      }
+
+      const DATA_TYPE& operator[](const unsigned column) const
+      {
+         gmtlASSERT(column < COLS);
+         return (*mMat)(mRow,column);
+      }
+
+      const Matrix<DATA_TYPE,ROWS,COLS>*  mMat;
+      unsigned                      mRow;    /** The row being accessed */
+   };
+
+   /** describes the xforms that this matrix has been through. */
+   enum XformState
+   {
+      // identity matrix.
+      IDENTITY = 1,
+
+      // only translation, can simply negate that column
+      TRANS = 2,
+
+      // able to tranpose to get the inverse.  only rotation component is set
+      ORTHOGONAL = 4,
+
+      // orthogonal, and normalized axes.
+      //ORTHONORMAL = 8,
+
+      // leaves the homogeneous coordinate unchanged - that is, in which the last column is (0,0,0,s).
+      // can include rotation, uniform scale, and translation, but no shearing or nonuniform scaling
+      // This can optionally be combined with the NON_UNISCALE state to indicate there is also non-uniform scale
+      AFFINE = 16,
+
+      // AFFINE matrix with non-uniform scale, a matrix cannot
+      // have this state without also having AFFINE (must be or'd together).
+      NON_UNISCALE = 32,
+
+      // fully set matrix containing more information than the above, or state is unknown,
+      // or unclassifiable in terms of the above.
+      FULL = 64,
+
+      // error bit
+      XFORM_ERROR = 128
+   };
+
+   /** Default Constructor (Identity constructor) */
+   Matrix()
+   {
+      /** @todo mp */
+      for (unsigned int r = 0; r < ROWS; ++r)
+      {
+         for (unsigned int c = 0; c < COLS; ++c)
+         {   this->operator()( r, c ) = (DATA_TYPE)0.0; }
+      }
+
+      /** @todo mp */
+      for (unsigned int x = 0; x < Math::Min( COLS, ROWS ); ++x)
+      {  this->operator()( x, x ) = (DATA_TYPE)1.0; }
+
+      /** @todo Set initial state to IDENTITY and test other stuff */
+      mState = IDENTITY;
+   }
+
+   /** copy constructor */
+   Matrix( const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
+   {
+      this->set( matrix.getData() );
+      mState = matrix.mState;
+   }
+
+   /** element wise setter for 2x2.
+    * @note variable names specify the row,column number to put the data into
+    *  @todo needs mp!!
+    */
+   void set( DATA_TYPE v00, DATA_TYPE v01,
+             DATA_TYPE v10, DATA_TYPE v11 )
+   {
+      GMTL_STATIC_ASSERT( (ROWS == 2 && COLS == 2), Set_called_when_Matrix_not_of_size_2_2 );
+      mData[0] = v00;
+      mData[1] = v10;
+      mData[2] = v01;
+      mData[3] = v11;
+      mState = FULL;
+   }
+
+   /** element wise setter for 2x3.
+    * @todo needs mp!!
+    */
+   void set( DATA_TYPE v00, DATA_TYPE v01, DATA_TYPE v02,
+             DATA_TYPE v10, DATA_TYPE v11, DATA_TYPE v12  )
+   {
+      GMTL_STATIC_ASSERT( (ROWS == 2 && COLS == 3), Set_called_when_Matrix_not_of_size_2_3 );
+      mData[0] = v00;
+      mData[1] = v10;
+      mData[2] = v01;
+      mData[3] = v11;
+      mData[4] = v02;
+      mData[5] = v12;
+      mState = FULL;
+   }
+
+   /** element wise setter for 3x3.
+    * @todo needs mp!!
+    */
+   void set( DATA_TYPE v00, DATA_TYPE v01, DATA_TYPE v02,
+             DATA_TYPE v10, DATA_TYPE v11, DATA_TYPE v12,
+             DATA_TYPE v20, DATA_TYPE v21, DATA_TYPE v22)
+   {
+      GMTL_STATIC_ASSERT( (ROWS == 3 && COLS == 3), Set_called_when_Matrix_not_of_size_3_3 );
+      mData[0] = v00;
+      mData[1] = v10;
+      mData[2] = v20;
+
+      mData[3] = v01;
+      mData[4] = v11;
+      mData[5] = v21;
+
+      mData[6] = v02;
+      mData[7] = v12;
+      mData[8] = v22;
+      mState = FULL;
+   }
+
+   /** element wise setter for 3x4.
+    * @todo needs mp!!  currently no way for a 4x3, ....
+    */
+   void set( DATA_TYPE v00, DATA_TYPE v01, DATA_TYPE v02, DATA_TYPE v03,
+             DATA_TYPE v10, DATA_TYPE v11, DATA_TYPE v12, DATA_TYPE v13,
+             DATA_TYPE v20, DATA_TYPE v21, DATA_TYPE v22, DATA_TYPE v23)
+   {
+      GMTL_STATIC_ASSERT( (ROWS == 3 && COLS == 4), Set_called_when_Matrix_not_of_size_3_4 );
+      mData[0] = v00;
+      mData[1] = v10;
+      mData[2] = v20;
+      mData[3] = v01;
+      mData[4] = v11;
+      mData[5] = v21;
+      mData[6] = v02;
+      mData[7] = v12;
+      mData[8] = v22;
+
+      // right row
+      mData[9]  = v03;
+      mData[10] = v13;
+      mData[11] = v23;
+      mState = FULL;
+   }
+
+   /** element wise setter for 4x4.
+    * @todo needs mp!!  currently no way for a 4x3, ....
+    */
+   void set( DATA_TYPE v00, DATA_TYPE v01, DATA_TYPE v02, DATA_TYPE v03,
+             DATA_TYPE v10, DATA_TYPE v11, DATA_TYPE v12, DATA_TYPE v13,
+             DATA_TYPE v20, DATA_TYPE v21, DATA_TYPE v22, DATA_TYPE v23,
+             DATA_TYPE v30, DATA_TYPE v31, DATA_TYPE v32, DATA_TYPE v33 )
+   {
+      GMTL_STATIC_ASSERT( (ROWS == 4 && COLS == 4), Set_called_when_Matrix_not_of_size_4_4 );
+      mData[0]  = v00;
+      mData[1]  = v10;
+      mData[2]  = v20;
+      mData[4]  = v01;
+      mData[5]  = v11;
+      mData[6]  = v21;
+      mData[8]  = v02;
+      mData[9]  = v12;
+      mData[10] = v22;
+
+      // right row
+      mData[12] = v03;
+      mData[13] = v13;
+      mData[14] = v23;
+
+      // bottom row
+      mData[3]  = v30;
+      mData[7]  = v31;
+      mData[11] = v32;
+      mData[15] = v33;
+      mState = FULL;
+   }
+
+   /** comma operator
+    *  @todo implement this!
+    */
+   //void operator,()( DATA_TYPE b ) {}
+
+   /** set the matrix to the given data.
+    *  This function is useful to copy matrix data from another math library.
+    *
+    * <h3> "Example (to a matrix using an external math library):" </h3>
+    * \code
+    *    pfMatrix other_matrix;
+    *    other_matrix.setRot( 90, 1, 0, 0 );
+    *
+    *    gmtl::Matrix44f mat;
+    *    mat.set( other_matrix.getFloatPtr() );
+    * \endcode
+    *
+    *  WARNING: this isn't really safe, size and datatype are not enforced by
+    *           the compiler.
+    * @pre data is in the native format of the gmtl::Matrix class, if not,
+    *      then you might be able to use the setTranspose function.
+    * @pre i.e. in a 4x4 data[0-3] is the 1st column, data[4-7] is 2nd, etc...
+    */
+   void set( const DATA_TYPE* data )
+   {
+      /** @todo mp */
+      for (unsigned int x = 0; x < ROWS * COLS; ++x)
+         mData[x] = data[x];
+      mState = FULL;
+   }
+
+   /** set the matrix to the transpose of the given data.
+    * normally set() takes raw matrix data in column by column order,
+    * this function allows you to pass in row by row data.
+    *
+    * Normally you'll use this function if you want to use a float array
+    * to init the matrix (see code example).
+    *
+    * <h3> "Example (to set a [15 -4 20] translation using float array):" </h3>
+    * \code
+    *    float data[] = { 1, 0, 0, 15,
+    *                     0, 1, 0, -4,
+    *                     0, 0, 1, 20,
+    *                     0, 0, 0, 1   };
+    *    gmtl::Matrix44f mat;
+    *    mat.setTranspose( data );
+    * \endcode
+    *
+    *  WARNING: this isn't really safe, size and datatype are not enforced by
+    *           the compiler.
+    * @pre ptr is in the transpose of the native format of the Matrix class
+    * @pre i.e. in a 4x4 data[0-3] is the 1st row, data[4-7] is 2nd, etc...
+    */
+   void setTranspose( const DATA_TYPE* data )
+   {
+      /** @todo metaprog */
+      for (unsigned int r = 0; r < ROWS; ++r)
+      for (unsigned int c = 0; c < COLS; ++c)
+         this->operator()( r, c ) = data[(r * COLS) + c];
+      mState = FULL;
+   }
+
+   /** access [row, col] in the matrix
+    *  WARNING: If you set data in the matrix (using this interface),
+    *  you are required to set mState
+    *  appropriately, failure to do so will result in incorrect
+    *  calculations by other functions in GMTL.  If you are unsure
+    *  about how to set mState, set it to FULL and you will be sure
+    *  to get the correct result at the cost of some performance.
+    */
+   DATA_TYPE& operator()( const unsigned row, const unsigned column )
+   {
+      gmtlASSERT( (row < ROWS) && (column < COLS) );
+      return mData[column*ROWS + row];
+   }
+
+   /** access [row, col] in the matrix (const version) */
+   const DATA_TYPE&  operator()( const unsigned row, const unsigned column ) const
+   {
+      gmtlASSERT( (row < ROWS) && (column < COLS) );
+      return mData[column*ROWS + row];
+   }
+
+   /** bracket operator
+    *  WARNING: If you set data in the matrix (using this interface),
+    *  you are required to set mState
+    *  appropriately, failure to do so will result in incorrect
+    *  calculations by other functions in GMTL.  If you are unsure
+    *  about how to set mState, set it to FULL and you will be sure
+    *  to get the correct result at the cost of some performance.
+    */
+   RowAccessor operator[]( const unsigned row )
+   {
+      return RowAccessor(this, row);
+   }
+
+   /** bracket operator (const version) */
+   ConstRowAccessor operator[]( const unsigned row ) const
+   {
+      return ConstRowAccessor( this, row );
+   }
+
+   /*
+   // bracket operator
+   const DATA_TYPE& operator[]( const unsigned i ) const
+   {
+      gmtlASSERT( i < (ROWS*COLS) );
+      return mData[i];
+   }
+   */
+
+   /** Gets a DATA_TYPE pointer to the matrix data.
+    * @return Returns a pointer to the head of the matrix data.
+    */
+   const DATA_TYPE*  getData() const { return (DATA_TYPE*)mData; }
+
+   bool isError()
+   {
+      return mState & XFORM_ERROR;
+   }
+   void setError()
+   {
+      mState |= XFORM_ERROR;
+   }
+
+   void setState(int state)
+   { mState = state; }
+
+public:
+   /** Column major.  In other words {Column1, Column2, Column3, Column4} in memory
+    * access element mData[column][row]
+    *  WARNING: If you set data in the matrix (using this interface),
+    *  you are required to set mState appropriately,
+    *  failure to do so will result in incorrect
+    *  calculations by other functions in GMTL.  If you are unsure
+    *  about how to set mState, set it to FULL and you will be sure
+    *  to get the correct result at the cost of some performance.
+    */
+   DATA_TYPE mData[COLS*ROWS];
+
+   /** describes what xforms are in this matrix */
+   int mState;
+};
+
+typedef Matrix<float, 2, 2> Matrix22f;
+typedef Matrix<double, 2, 2> Matrix22d;
+typedef Matrix<float, 2, 3> Matrix23f;
+typedef Matrix<double, 2, 3> Matrix23d;
+typedef Matrix<float, 3, 3> Matrix33f;
+typedef Matrix<double, 3, 3> Matrix33d;
+typedef Matrix<float, 3, 4> Matrix34f;
+typedef Matrix<double, 3, 4> Matrix34d;
+typedef Matrix<float, 4, 4> Matrix44f;
+typedef Matrix<double, 4, 4> Matrix44d;
+
+/** 32bit floating point 2x2 identity matrix */
+const Matrix22f MAT_IDENTITY22F = Matrix22f();
+
+/** 64bit floating point 2x2 identity matrix */
+const Matrix22d MAT_IDENTITY22D = Matrix22d();
+
+/** 32bit floating point 2x2 identity matrix */
+const Matrix23f MAT_IDENTITY23F = Matrix23f();
+
+/** 64bit floating point 2x2 identity matrix */
+const Matrix23d MAT_IDENTITY23D = Matrix23d();
+
+/** 32bit floating point 3x3 identity matrix */
+const Matrix33f MAT_IDENTITY33F = Matrix33f();
+
+/** 64bit floating point 3x3 identity matrix */
+const Matrix33d MAT_IDENTITY33D = Matrix33d();
+
+/** 32bit floating point 3x4 identity matrix */
+const Matrix34f MAT_IDENTITY34F = Matrix34f();
+
+/** 64bit floating point 3x4 identity matrix */
+const Matrix34d MAT_IDENTITY34D = Matrix34d();
+
+/** 32bit floating point 4x4 identity matrix */
+const Matrix44f MAT_IDENTITY44F = Matrix44f();
+
+/** 64bit floating point 4x4 identity matrix */
+const Matrix44d MAT_IDENTITY44D = Matrix44d();
+
+/** utility function for use by matrix operations.
+ *  given two matrices, when combined with set(..) or xform(..) types of operations,
+ *  compute what matrixstate will the resulting matrix have?
+ */
+inline int combineMatrixStates( int state1, int state2 )
+{
+   switch (state1)
+   {
+   case Matrix44f::IDENTITY:
+      switch (state2)
+      {
+      case Matrix44f::XFORM_ERROR: return state2;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      default: return state2;
+      }
+   case Matrix44f::TRANS:
+      switch (state2)
+      {
+      case Matrix44f::IDENTITY: return state1;
+      case Matrix44f::ORTHOGONAL: return Matrix44f::AFFINE;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      default: return state2;
+      }
+   case Matrix44f::ORTHOGONAL:
+      switch (state2)
+      {
+      case Matrix44f::IDENTITY: return state1;
+      case Matrix44f::TRANS: return Matrix44f::AFFINE;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      default: return state2;
+      }
+   case Matrix44f::AFFINE:
+      switch (state2)
+      {
+      case Matrix44f::IDENTITY:
+      case Matrix44f::TRANS:
+      case Matrix44f::ORTHOGONAL:  return state1;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      case Matrix44f::AFFINE | Matrix44f::NON_UNISCALE:
+      default: return state2;
+      }
+   case Matrix44f::AFFINE | Matrix44f::NON_UNISCALE:
+      switch (state2)
+      {
+      case Matrix44f::IDENTITY:
+      case Matrix44f::TRANS:
+      case Matrix44f::ORTHOGONAL:
+      case Matrix44f::AFFINE:  return state1;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      default: return state2;
+      }
+   case Matrix44f::FULL:
+      switch (state2)
+      {
+      case Matrix44f::XFORM_ERROR: return state2;
+      case Matrix44f::NON_UNISCALE: return Matrix44f::XFORM_ERROR;
+      default: return state1;
+      }
+      break;
+   default:
+      return Matrix44f::XFORM_ERROR;
+   }
+}
+
+} // end namespace gmtl
+
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/MatrixOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/MatrixOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/MatrixOps.h	(revision 4)
@@ -0,0 +1,770 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          MatrixOps.h,v
+ * Date modified: 2005/05/16 14:19:44
+ * Version:       1.39
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_MATRIXOPS_H_
+#define _GMTL_MATRIXOPS_H_
+
+#include <iostream>         // for std::cerr
+#include <algorithm>        // needed for std::swap
+#include <gmtl/Matrix.h>
+#include <gmtl/Math.h>
+#include <gmtl/Vec.h>
+#include <gmtl/VecOps.h>
+#include <gmtl/Util/Assert.h>
+
+namespace gmtl
+{
+/** @ingroup Ops
+ * @name Matrix Operations
+ * @{
+ */
+
+   /** Make identity matrix out the matrix.
+    * @post Every element is 0 except the matrix's diagonal, whose elements are 1.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& identity( Matrix<DATA_TYPE, ROWS, COLS>& result )
+   {
+      if(result.mState != Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY)   // if not already ident
+      {
+         // TODO: mp
+         for (unsigned int r = 0; r < ROWS; ++r)
+         for (unsigned int c = 0; c < COLS; ++c)
+            result( r, c ) = (DATA_TYPE)0.0;
+
+         // TODO: mp
+         for (unsigned int x = 0; x < Math::Min( COLS, ROWS ); ++x)
+            result( x, x ) = (DATA_TYPE)1.0;
+
+         result.mState = Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY;
+//         result.mState = Matrix<DATA_TYPE, ROWS, COLS>::FULL;
+      }
+
+      return result;
+   }
+
+
+   /** zero out the matrix.
+    * @post every element is 0.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& zero( Matrix<DATA_TYPE, ROWS, COLS>& result )
+   {
+      if (result.mState == Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY)
+      {
+         for (unsigned int x = 0; x < Math::Min( ROWS, COLS ); ++x)
+         {
+            result( x, x ) = (DATA_TYPE)0;
+         }
+      }
+      else
+      {
+         for (unsigned int x = 0; x < ROWS*COLS; ++x)
+         {
+            result.mData[x] = (DATA_TYPE)0;
+         }
+      }
+      result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL;
+      return result;
+   }
+
+
+   /** matrix multiply.
+    *  @PRE: With regard to size (ROWS/COLS): if lhs is m x p, and rhs is p x n, then result is m x n (mult func undefined otherwise)
+    *  @POST: returns a m x n sized matrix
+    *  @post: result = lhs * rhs  (where rhs is applied first)
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned INTERNAL, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                 const Matrix<DATA_TYPE, ROWS, INTERNAL>& lhs,
+                 const Matrix<DATA_TYPE, INTERNAL, COLS>& rhs )
+   {
+      Matrix<DATA_TYPE, ROWS, COLS> ret_mat; // prevent aliasing
+      zero( ret_mat );
+
+      // p. 150 Numerical Analysis (second ed.)
+      // if A is m x p, and B is p x n, then AB is m x n
+      // (AB)ij  =  [k = 1 to p] (a)ik (b)kj     (where:  1 <= i <= m, 1 <= j <= n)
+      for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
+      for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
+      for (unsigned int k = 0; k < INTERNAL; ++k)       // [k = 1 to p]
+         ret_mat( i, j ) += lhs( i, k ) * rhs( k, j );
+
+      // track state
+      ret_mat.mState = combineMatrixStates( lhs.mState, rhs.mState );
+      return result = ret_mat;
+   }
+
+   /** matrix * matrix.
+    *  @PRE: With regard to size (ROWS/COLS): if lhs is m x p, and rhs is p x n, then result is m x n (mult func undefined otherwise)
+    *  @POST: returns a m x n sized matrix == lhs * rhs (where rhs is applied first)
+    *  returns a temporary, is slower.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned INTERNAL, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS> operator*( const Matrix<DATA_TYPE, ROWS, INTERNAL>& lhs,
+                                                   const Matrix<DATA_TYPE, INTERNAL, COLS>& rhs )
+   {
+      Matrix<DATA_TYPE, ROWS, COLS> temporary;
+      return mult( temporary, lhs, rhs );
+   }
+
+   /** matrix subtraction (algebraic operation for matrix).
+    *  @PRE: if lhs is m x n, and rhs is m x n, then result is m x n (mult func undefined otherwise)
+    *  @POST: returns a m x n matrix
+    *  @TODO: <B>enforce the sizes with templates...</b>
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& sub( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                 const Matrix<DATA_TYPE, ROWS, COLS>& lhs,
+                 const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
+   {
+      // p. 150 Numerical Analysis (second ed.)
+      // if A is m x n, and B is m x n, then AB is m x n
+      // (A - B)ij  = (a)ij - (b)ij     (where:  1 <= i <= m, 1 <= j <= n)
+      for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
+      for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
+         result( i, j ) = lhs( i, j ) - rhs( i, j );
+
+      // track state
+      result.mState = combineMatrixStates( lhs.mState, rhs.mState );
+      return result;
+   }
+
+   /** matrix addition (algebraic operation for matrix).
+    *  @PRE: if lhs is m x n, and rhs is m x n, then result is m x n (mult func undefined otherwise)
+    *  @POST: returns a m x n matrix
+    *  TODO: <B>enforce the sizes with templates...</b>
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& add( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                 const Matrix<DATA_TYPE, ROWS, COLS>& lhs,
+                 const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
+   {
+      // p. 150 Numerical Analysis (second ed.)
+      // if A is m x n, and B is m x n, then AB is m x n
+      // (A - B)ij  = (a)ij + (b)ij     (where:  1 <= i <= m, 1 <= j <= n)
+      for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
+      for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
+         result( i, j ) = lhs( i, j ) + rhs( i, j );
+
+      // track state
+      result.mState = combineMatrixStates( lhs.mState, rhs.mState );
+      return result;
+   }
+
+   /** matrix postmultiply.
+    * @PRE: args must both be n x n (this function is undefined otherwise)
+    * @POST: result' = result * operand
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Matrix<DATA_TYPE, SIZE, SIZE>& postMult( Matrix<DATA_TYPE, SIZE, SIZE>& result,
+                                                     const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
+   {
+      return mult( result, result, operand );
+   }
+
+   /** matrix preMultiply.
+    * @PRE: args must both be n x n (this function is undefined otherwise)
+    * @POST: result' = operand * result
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Matrix<DATA_TYPE, SIZE, SIZE>& preMult( Matrix<DATA_TYPE, SIZE, SIZE>& result,
+                                                  const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
+   {
+      return mult( result, operand, result );
+   }
+
+   /** matrix postmult (operator*=).
+    * does a postmult on the matrix.
+    * @PRE: args must both be n x n sized (this function is undefined otherwise)
+    * @POST: result' = result * operand  (where operand is applied first)
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Matrix<DATA_TYPE, SIZE, SIZE>& operator*=( Matrix<DATA_TYPE, SIZE, SIZE>& result,
+                                                     const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
+   {
+      return postMult( result, operand );
+   }
+
+   /** matrix scalar mult.
+    *  mult each elt in a matrix by a scalar value.
+    *  @POST: result = mat * scalar
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& mat, const DATA_TYPE& scalar )
+   {
+      for (unsigned i = 0; i < ROWS * COLS; ++i)
+         result.mData[i] = mat.mData[i] * scalar;
+      result.mState = mat.mState;
+      return result;
+   }
+
+   /** matrix scalar mult.
+    * mult each elt in a matrix by a scalar value.
+    *  @POST: result *= scalar
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result, DATA_TYPE scalar )
+   {
+      for (unsigned i = 0; i < ROWS * COLS; ++i)
+         result.mData[i] *= scalar;
+      return result;
+   }
+
+   /** matrix scalar mult (operator*=).
+    * multiply matrix elements by a scalar
+    * @POST: result *= scalar
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& operator*=( Matrix<DATA_TYPE, ROWS, COLS>& result, const DATA_TYPE& scalar )
+   {
+      return mult( result, scalar );
+   }
+
+   /** matrix transpose in place.
+    *  @PRE:  needs to be an N x N matrix
+    *  @POST: flip along diagonal
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   Matrix<DATA_TYPE, SIZE, SIZE>& transpose( Matrix<DATA_TYPE, SIZE, SIZE>& result )
+   {
+      // p. 27 game programming gems #1
+      for (unsigned c = 0; c < SIZE; ++c)
+         for (unsigned r = c + 1; r < SIZE; ++r)
+            std::swap( result( r, c ), result( c, r ) );
+
+      return result;
+   }
+
+   /** matrix transpose from one type to another (i.e. 3x4 to 4x3)
+    *  @PRE:  source needs to be an M x N matrix, while dest needs to be N x M
+    *  @POST: flip along diagonal
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   Matrix<DATA_TYPE, ROWS, COLS>& transpose( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, COLS, ROWS>& source )
+   {
+      // in case result is == source... :(
+      Matrix<DATA_TYPE, COLS, ROWS> temp = source;
+
+      // p. 149 Numerical Analysis (second ed.)
+      for (unsigned i = 0; i < ROWS; ++i)
+      {
+         for (unsigned j = 0; j < COLS; ++j)
+         {
+            result( i, j ) = temp( j, i );
+         }
+      }
+      result.mState = temp.mState;
+      return result;
+   }
+
+   /** translational matrix inversion.
+    *  Matrix inversion that acts on a translational matrix (matrix with only translation)
+    *  Check for error with Matrix::isError().
+    * @pre: 4x3, 4x4 matrices only
+    * @post: result' = inv( result )
+    * @post: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invertTrans( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                       const Matrix<DATA_TYPE, ROWS, COLS>& src )
+   {
+      gmtlASSERT( ROWS == COLS || COLS == ROWS+1 && "invertTrans supports NxN or Nx(N-1) matrices only" );
+
+      if (&result != &src)
+         result = src; // could optimise this a little more (skip the trans copy), favor simplicity for now...
+      for (unsigned x = 0; x < (ROWS-1+(COLS-ROWS)); ++x)
+      {
+         result[x][3] = -result[x][3];
+      }
+      return result;
+   }
+
+   /** orthogonal matrix inversion.
+    *  Matrix inversion that acts on a affine matrix (matrix with only trans, rot, uniform scale)
+    *  Check for error with Matrix::isError().
+    * @pre: any size matrix
+    * @post: result' = inv( result )
+    * @post: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invertOrthogonal( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                       const Matrix<DATA_TYPE, ROWS, COLS>& src )
+   {
+      // in case result is == source... :(
+      Matrix<DATA_TYPE, ROWS, COLS> temp = src;
+
+      // if 3x4, 2x3, etc...  can't transpose the last column
+      const unsigned int size = Math::Min( ROWS, COLS );
+
+      // p. 149 Numerical Analysis (second ed.)
+      for (unsigned i = 0; i < size; ++i)
+      {
+         for (unsigned j = 0; j < size; ++j)
+         {
+            result( i, j ) = temp( j, i );
+         }
+      }
+      result.mState = temp.mState;
+      return result;
+   }
+
+   /** affine matrix inversion.
+    *  Matrix inversion that acts on a 4x3 affine matrix (matrix with only trans, rot, uniform scale)
+    *  Check for error with Matrix::isError().
+    * @pre: 3x3, 4x3, 4x4 matrices only
+    * @POST: result' = inv( result )
+    * @POST: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invertAffine( Matrix<DATA_TYPE, ROWS, COLS>& result,
+                                                       const Matrix<DATA_TYPE, ROWS, COLS>& source )
+   {
+      static const float eps = 0.00000001f;
+
+      // in case &result is == &source... :(
+      Matrix<DATA_TYPE, ROWS, COLS> src = source;
+
+      // The rotational part of the matrix is simply the transpose of the
+      // original matrix.
+      for (int x = 0; x < 3; ++x)
+      for (int y = 0; y < 3; ++y)
+      {
+         result[x][y] = src[y][x];
+      }
+
+      // do non-uniform scale inversion
+      if (src.mState & Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE)
+      {
+         DATA_TYPE l0 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[0][0], result[0][1], result[0][2] ) );
+         DATA_TYPE l1 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[1][0], result[1][1], result[1][2] ) );
+         DATA_TYPE l2 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[2][0], result[2][1], result[2][2] ) );
+         if (gmtl::Math::abs( l0 ) > eps) l0 = 1.0f / l0;
+         if (gmtl::Math::abs( l1 ) > eps) l1 = 1.0f / l1;
+         if (gmtl::Math::abs( l2 ) > eps) l2 = 1.0f / l2;
+         // apply the inverse scale to the 3x3
+         // for each axis: normalize it (1/length), and then mult by inverse scale (1/length)
+         result[0][0] *= l0;
+         result[0][1] *= l0;
+         result[0][2] *= l0;
+         result[1][0] *= l1;
+         result[1][1] *= l1;
+         result[1][2] *= l1;
+         result[2][0] *= l2;
+         result[2][1] *= l2;
+         result[2][2] *= l2;
+      }
+
+      // handle matrices with translation
+      if (COLS == 4)
+      {
+         // The right column vector of the matrix should always be [ 0 0 0 s ]
+         // this represents some shear values
+         result[3][0] = result[3][1] = result[3][2] = 0;
+
+         // The translation components of the original matrix.
+         const DATA_TYPE& tx = src[0][3];
+         const DATA_TYPE& ty = src[1][3];
+         const DATA_TYPE& tz = src[2][3];
+
+
+         // Rresult = -(Tm * Rm) to get the translation part of the inverse
+         if (ROWS == 4)
+         {
+            // invert scale.
+            const DATA_TYPE tw = (gmtl::Math::abs( src[3][3] ) > eps) ? 1.0f / src[3][3] : 0.0f;
+
+            // handle uniform scale in Nx4 matrices
+            result[0][3] = -( result[0][0] * tx + result[0][1] * ty + result[0][2] * tz ) * tw;
+            result[1][3] = -( result[1][0] * tx + result[1][1] * ty + result[1][2] * tz ) * tw;
+            result[2][3] = -( result[2][0] * tx + result[2][1] * ty + result[2][2] * tz ) * tw;
+            result[3][3] = tw;
+         }
+         else if (ROWS == 3)
+         {
+            result[0][3] = -( result[0][0] * tx + result[0][1] * ty + result[0][2] * tz );
+            result[1][3] = -( result[1][0] * tx + result[1][1] * ty + result[1][2] * tz );
+            result[2][3] = -( result[2][0] * tx + result[2][1] * ty + result[2][2] * tz );
+         }
+      }
+
+
+
+      result.mState = src.mState;
+
+      return result;
+   }
+
+   /** Full matrix inversion using Gauss-Jordan elimination.
+    *  Check for error with Matrix::isError().
+    * @POST: result' = inv( result )
+    * @POST: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Matrix<DATA_TYPE, SIZE, SIZE>& invertFull_GJ( Matrix<DATA_TYPE, SIZE, SIZE>& result, const Matrix<DATA_TYPE, SIZE, SIZE>& src )
+   {
+      //gmtlASSERT( ROWS == COLS && "invertFull only works with nxn matrices" );
+
+      const DATA_TYPE pivot_eps(1e-20);         // Epsilon for the pivot value test (delta with test against zero)
+
+      // Computer inverse of matrix using a Gaussian-Jordan elimination.
+      // Uses max pivot at each point
+      // See: "Essential Mathmatics for Games" for description
+
+      // Do this invert in place
+      result = src;
+      unsigned swapped[SIZE];       // Track swaps. swapped[3] = 2 means that row 3 was swapped with row 2
+
+      unsigned pivot;
+
+      // --- Gaussian elimination step --- //
+      // For each column and row
+      for(pivot=0; pivot<SIZE;++pivot)
+      {
+         unsigned    pivot_row(pivot);
+         DATA_TYPE   pivot_value(gmtl::Math::abs(result(pivot_row, pivot)));    // Initialize to beginning of current row
+
+         // find pivot row - (max pivot element)
+         for(unsigned pr=pivot+1;pr<SIZE;++pr)
+         {
+            const DATA_TYPE cur_val(gmtl::Math::abs(result(pr,pivot)));   // get value at current point
+            if (cur_val > pivot_value)
+            {
+               pivot_row = pr;
+               pivot_value = cur_val;
+            }
+         }
+
+         if(gmtl::Math::isEqual(DATA_TYPE(0),pivot_value,pivot_eps))
+         {
+            std::cerr << "*** pivot = " << pivot_value << " in mat_inv. ***\n";
+            result.setError();
+            return result;
+         }
+
+         // Check for swap of pivot rows
+         swapped[pivot] = pivot_row;
+         if(pivot_row != pivot)
+         {
+            for(unsigned c=0;c<SIZE;++c)
+            {  std::swap(result(pivot,c), result(pivot_row,c)); }
+         }
+         // ASSERT: row to use in now in "row" (check that row starts with max pivot value found)
+         gmtlASSERT(gmtl::Math::isEqual(pivot_value,gmtl::Math::abs(result(pivot,pivot)),DATA_TYPE(0.00001)));
+
+         // Compute pivot factor
+         const DATA_TYPE mult_factor(1.0f/pivot_value);
+
+         // Set pivot row values
+         for(unsigned c=0;c<SIZE;++c)
+         {  result(pivot,c) *= mult_factor; }
+         result(pivot,pivot) = mult_factor;    // Copy the 1/pivot since we are inverting in place
+
+         // Clear pivot column in other rows (since we are in place)
+         // - Subtract current row times result(r,col) so that column element becomes 0
+         for(unsigned row=0;row<SIZE;++row)
+         {
+            if(row==pivot)     // Don't subtract from our row
+            { continue; }
+
+            const DATA_TYPE sub_mult_factor(result(row,pivot));
+
+            // Clear the pivot column's element (for invers in place)
+            // ends up being set to -sub_mult_factor*pivotInverse
+            result(row,pivot) = 0;
+
+            // subtract the pivot row from this row
+            for(unsigned col=0;col<SIZE;++col)
+            {   result(row,col) -= (sub_mult_factor*result(pivot,col)); }
+         }
+      } // end: gaussian substitution
+
+
+      // Now undo the swaps in column direction in reverse order
+      unsigned p(SIZE);
+      do
+      {
+         --p;
+         gmtlASSERT(p<SIZE);
+
+         // If row was swapped
+         if(swapped[p] != p)
+         {
+            // Swap the column with same index
+            for(unsigned r=0; r<SIZE; ++r)
+            { std::swap(result(r, p), result(r, swapped[p])); }
+         }
+      }
+      while(p>0);
+
+      return result;
+   }
+
+
+   /** full matrix inversion.
+    *  Check for error with Matrix::isError().
+    * @POST: result' = inv( result )
+    * @POST: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned SIZE>
+   inline Matrix<DATA_TYPE, SIZE, SIZE>& invertFull_orig( Matrix<DATA_TYPE, SIZE, SIZE>& result, const Matrix<DATA_TYPE, SIZE, SIZE>& src )
+   {
+      /*---------------------------------------------------------------------------*
+       | mat_inv: Compute the inverse of a n x n matrix, using the maximum pivot   |
+       |          strategy.  n <= MAX1.                                            |
+       *---------------------------------------------------------------------------*
+
+         Parameters:
+             a        a n x n square matrix
+             b        inverse of input a.
+             n        dimenstion of matrix a.
+      */
+
+      const DATA_TYPE* a = src.getData();
+      DATA_TYPE* b = result.mData;
+
+      int   n(SIZE);
+      int    i, j, k;
+      int    r[SIZE], c[SIZE], row[SIZE], col[SIZE];
+      DATA_TYPE  m[SIZE][SIZE*2], pivot, max_m, tmp_m, fac;
+
+      /* Initialization */
+      for ( i = 0; i < n; i ++ )
+      {
+         r[ i] = c[ i] = 0;
+         row[ i] = col[ i] = 0;
+      }
+
+      /* Set working matrix */
+      for ( i = 0; i < n; i++ )
+      {
+         for ( j = 0; j < n; j++ )
+         {
+            m[ i][ j] = a[ i * n + j];
+            m[ i][ j + n] = ( i == j ) ? (DATA_TYPE)1.0 : (DATA_TYPE)0.0 ;
+         }
+      }
+
+      /* Begin of loop */
+      for ( k = 0; k < n; k++ )
+      {
+         /* Choosing the pivot */
+         for ( i = 0, max_m = 0; i < n; i++ )
+         {
+            if ( row[ i]  )
+               continue;
+            for ( j = 0; j < n; j++ )
+            {
+               if ( col[ j] )
+                  continue;
+               tmp_m = gmtl::Math::abs( m[ i][ j]);
+               if ( tmp_m > max_m)
+               {
+                  max_m = tmp_m;
+                  r[ k] = i;
+                  c[ k] = j;
+               }
+            }
+         }
+         row[ r[k] ] = col[ c[k] ] = 1;
+         pivot = m[ r[ k] ][ c[ k] ];
+
+
+         if ( gmtl::Math::abs( pivot) <= 1e-20)
+         {
+            std::cerr << "*** pivot = " << pivot << " in mat_inv. ***\n";
+            result.setError();
+            return result;
+         }
+
+         /* Normalization */
+         for ( j = 0; j < 2*n; j++ )
+         {
+            if ( j == c[ k] )
+               m[ r[ k]][ j] = (DATA_TYPE)1.0;
+            else
+               m[ r[ k]][ j] /= pivot;
+         }
+
+         /* Reduction */
+         for ( i = 0; i < n; i++ )
+         {
+            if ( i == r[ k] )
+               continue;
+
+            for ( j=0, fac = m[ i][ c[k]]; j < 2*n; j++ )
+            {
+               if ( j == c[ k] )
+                  m[ i][ j] = (DATA_TYPE)0.0;
+               else
+                  m[ i][ j] -= fac * m[ r[k]][ j];
+            }
+         }
+      }
+
+      /* Assign inverse to a matrix */
+      for ( i = 0; i < n; i++ )
+         for ( j = 0; j < n; j++ )
+            row[ i] = ( c[ j] == i ) ? r[ j] : row[ i];
+
+      for ( i = 0; i < n; i++ )
+         for ( j = 0; j < n; j++ )
+            b[ i * n +  j] = m[ row[ i]][ j + n];
+
+      // It worked
+      result.mState = src.mState;
+      return result;
+   }
+
+
+   /** Invert method.
+    * Calls invertFull_orig to do the work.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invertFull( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& src )
+   {
+      return invertFull_orig(result,src);
+   }
+
+   /** smart matrix inversion.
+    *  Does matrix inversion by intelligently selecting what type of inversion to use depending
+    *  on the types of operations your Matrix has been through.
+    *
+    *  5 types of inversion: FULL, AFFINE, ORTHONORMAL, ORTHOGONAL, IDENTITY.
+    *
+    *  Check for error with Matrix::isError().
+    * @POST: result' = inv( result )
+    * @POST: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invert( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& src )
+   {
+      if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY )
+         return result = src;
+      else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::TRANS)
+         return invertTrans( result, src );
+      else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL)
+         return invertOrthogonal( result, src );
+      else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::AFFINE ||
+               src.mState == (Matrix<DATA_TYPE, ROWS, COLS>::AFFINE | Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE))
+         return invertAffine( result, src );
+      else
+         return invertFull_orig( result, src );
+   }
+
+   /** smart matrix inversion (in place)
+    *  Does matrix inversion by intelligently selecting what type of inversion to use depending
+    *  on the types of operations your Matrix has been through.
+    *
+    *  5 types of inversion: FULL, AFFINE, ORTHONORMAL, ORTHOGONAL, IDENTITY.
+    *
+    *  Check for error with Matrix::isError().
+    * @POST: result' = inv( result )
+    * @POST: If inversion failed, then error bit is set within the Matrix.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Matrix<DATA_TYPE, ROWS, COLS>& invert( Matrix<DATA_TYPE, ROWS, COLS>& result )
+   {
+      return invert( result, result );
+   }
+
+/** @} */
+
+/** @ingroup Compare
+ * @name Matrix Comparitors
+ * @{
+ */
+
+   /** Tests 2 matrices for equality
+    *  @param lhs    The first matrix
+    *  @param rhs    The second matrix
+    *  @pre Both matrices must be of the same size.
+    *  @return true if the matrices have the same element values; false otherwise
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline bool operator==( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
+   {
+      for (unsigned int i = 0; i < ROWS*COLS; ++i)
+      {
+         if (lhs.mData[i] != rhs.mData[i])
+         {
+            return false;
+         }
+      }
+
+      return true;
+
+      /*  Would like this
+      return( lhs[0] == rhs[0] &&
+              lhs[1] == rhs[1] &&
+              lhs[2] == rhs[2] );
+      */
+   }
+
+   /** Tests 2 matrices for inequality
+    *  @param lhs    The first matrix
+    *  @param rhs    The second matrix
+    *  @pre Both matrices must be of the same size.
+    *  @return false if the matrices differ on any element value; true otherwise
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline bool operator!=( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
+   {
+      return bool( !(lhs == rhs) );
+   }
+
+   /** Tests 2 matrices for equality within a tolerance
+    *  @param lhs    The first matrix
+    *  @param rhs    The second matrix
+    *  @param eps    The tolerance value
+    *  @pre Both matrices must be of the same size.
+    *  @return true if the matrices' elements are within the tolerance value of each other; false otherwise
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline bool isEqual( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs, const DATA_TYPE eps = 0 )
+   {
+      gmtlASSERT( eps >= (DATA_TYPE)0 );
+
+      for (unsigned int i = 0; i < ROWS*COLS; ++i)
+      {
+         if (!Math::isEqual( lhs.mData[i], rhs.mData[i], eps ))
+            return false;
+      }
+      return true;
+   }
+/** @} */
+
+} // end of namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Numerics/Eigen.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Numerics/Eigen.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Numerics/Eigen.h	(revision 4)
@@ -0,0 +1,820 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Eigen.h,v
+ * Date modified: 2002/02/10 04:38:07
+ * Version:       1.4
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+//
+// XXX: Based on source code from: Magic Software, Inc.
+//
+#ifndef _EIGEN_H
+#define _EIGEN_H
+
+#include <gmtl/gmtlConfig.h>
+
+namespace gmtl
+{
+
+class Eigen
+{
+public:
+    Eigen (int iSize);
+    ~Eigen ();
+
+    // set the matrix for eigensolving
+    float& Matrix (int iRow, int iCol);
+    void SetMatrix (float** aafMat);
+
+    // get the results of eigensolving (eigenvectors are columns of matrix)
+    float GetEigenvalue (int i) const;
+    float GetEigenvector (int iRow, int iCol) const;
+    float* GetEigenvalue ();
+    float** GetEigenvector ();
+
+    // solve eigensystem
+    void EigenStuff2 ();
+    void EigenStuff3 ();
+    void EigenStuff4 ();
+    void EigenStuffN ();
+    void EigenStuff  ();
+
+    // solve eigensystem, use decreasing sort on eigenvalues
+    void DecrSortEigenStuff2 ();
+    void DecrSortEigenStuff3 ();
+    void DecrSortEigenStuff4 ();
+    void DecrSortEigenStuffN ();
+    void DecrSortEigenStuff  ();
+
+    // solve eigensystem, use increasing sort on eigenvalues
+    void IncrSortEigenStuff2 ();
+    void IncrSortEigenStuff3 ();
+    void IncrSortEigenStuff4 ();
+    void IncrSortEigenStuffN ();
+    void IncrSortEigenStuff  ();
+
+protected:
+    int m_iSize;
+    float** m_aafMat;
+    float* m_afDiag;
+    float* m_afSubd;
+
+    // Householder reduction to tridiagonal form
+    static void Tridiagonal2 (float** aafMat, float* afDiag,
+        float* afSubd);
+    static void Tridiagonal3 (float** aafMat, float* afDiag,
+        float* afSubd);
+    static void Tridiagonal4 (float** aafMat, float* afDiag,
+        float* afSubd);
+    static void TridiagonalN (int iSize, float** aafMat, float* afDiag,
+        float* afSubd);
+
+    // QL algorithm with implicit shifting, applies to tridiagonal matrices
+    static bool QLAlgorithm (int iSize, float* afDiag, float* afSubd,
+        float** aafMat);
+
+    // sort eigenvalues from largest to smallest
+    static void DecreasingSort (int iSize, float* afEigval,
+        float** aafEigvec);
+
+    // sort eigenvalues from smallest to largest
+    static void IncreasingSort (int iSize, float* afEigval,
+        float** aafEigvec);
+};
+
+//---------------------------------------------------------------------------
+inline float& Eigen::Matrix (int iRow, int iCol)
+{
+    return m_aafMat[iRow][iCol];
+}
+//---------------------------------------------------------------------------
+inline float Eigen::GetEigenvalue (int i) const
+{
+    return m_afDiag[i];
+}
+//---------------------------------------------------------------------------
+inline float Eigen::GetEigenvector (int iRow, int iCol) const
+{
+    return m_aafMat[iRow][iCol];
+}
+//---------------------------------------------------------------------------
+inline float* Eigen::GetEigenvalue ()
+{
+    return m_afDiag;
+}
+//---------------------------------------------------------------------------
+inline float** Eigen::GetEigenvector ()
+{
+    return m_aafMat;
+}
+//---------------------------------------------------------------------------
+
+
+
+
+
+//---------------------------------------------------------------------------
+Eigen::Eigen (int iSize)
+{
+    assert( iSize >= 2 );
+    m_iSize = iSize;
+
+    m_aafMat = new float*[m_iSize];
+    for (int i = 0; i < m_iSize; i++)
+        m_aafMat[i] = new float[m_iSize];
+
+    m_afDiag = new float[m_iSize];
+    m_afSubd = new float[m_iSize];
+}
+//---------------------------------------------------------------------------
+Eigen::~Eigen ()
+{
+    delete[] m_afSubd;
+    delete[] m_afDiag;
+    for (int i = 0; i < m_iSize; i++)
+        delete[] m_aafMat[i];
+    delete[] m_aafMat;
+}
+//---------------------------------------------------------------------------
+void Eigen::Tridiagonal2 (float** m_aafMat, float* m_afDiag,
+    float* m_afSubd)
+{
+    // matrix is already tridiagonal
+    m_afDiag[0] = m_aafMat[0][0];
+    m_afDiag[1] = m_aafMat[1][1];
+    m_afSubd[0] = m_aafMat[0][1];
+    m_afSubd[1] = 0.0;
+    m_aafMat[0][0] = 1.0;
+    m_aafMat[0][1] = 0.0;
+    m_aafMat[1][0] = 0.0;
+    m_aafMat[1][1] = 1.0;
+}
+//---------------------------------------------------------------------------
+void Eigen::Tridiagonal3 (float** m_aafMat, float* m_afDiag,
+    float* m_afSubd)
+{
+    float fM00 = m_aafMat[0][0];
+    float fM01 = m_aafMat[0][1];
+    float fM02 = m_aafMat[0][2];
+    float fM11 = m_aafMat[1][1];
+    float fM12 = m_aafMat[1][2];
+    float fM22 = m_aafMat[2][2];
+
+    m_afDiag[0] = fM00;
+    m_afSubd[2] = 0.0;
+    if ( fM02 != 0.0 )
+    {
+        float fLength = Math::sqrt(fM01*fM01+fM02*fM02);
+        float fInvLength = 1.0/fLength;
+        fM01 *= fInvLength;
+        fM02 *= fInvLength;
+        float fQ = 2.0*fM01*fM12+fM02*(fM22-fM11);
+        m_afDiag[1] = fM11+fM02*fQ;
+        m_afDiag[2] = fM22-fM02*fQ;
+        m_afSubd[0] = fLength;
+        m_afSubd[1] = fM12-fM01*fQ;
+        m_aafMat[0][0] = 1.0; m_aafMat[0][1] = 0.0;  m_aafMat[0][2] = 0.0;
+        m_aafMat[1][0] = 0.0; m_aafMat[1][1] = fM01; m_aafMat[1][2] = fM02;
+        m_aafMat[2][0] = 0.0; m_aafMat[2][1] = fM02; m_aafMat[2][2] = -fM01;
+    }
+    else
+    {
+        m_afDiag[1] = fM11;
+        m_afDiag[2] = fM22;
+        m_afSubd[0] = fM01;
+        m_afSubd[1] = fM12;
+        m_aafMat[0][0] = 1.0; m_aafMat[0][1] = 0.0; m_aafMat[0][2] = 0.0;
+        m_aafMat[1][0] = 0.0; m_aafMat[1][1] = 1.0; m_aafMat[1][2] = 0.0;
+        m_aafMat[2][0] = 0.0; m_aafMat[2][1] = 0.0; m_aafMat[2][2] = 1.0;
+    }
+}
+//---------------------------------------------------------------------------
+void Eigen::Tridiagonal4 (float** m_aafMat, float* m_afDiag,
+    float* m_afSubd)
+{
+    // save matrix M
+    float fM00 = m_aafMat[0][0];
+    float fM01 = m_aafMat[0][1];
+    float fM02 = m_aafMat[0][2];
+    float fM03 = m_aafMat[0][3];
+    float fM11 = m_aafMat[1][1];
+    float fM12 = m_aafMat[1][2];
+    float fM13 = m_aafMat[1][3];
+    float fM22 = m_aafMat[2][2];
+    float fM23 = m_aafMat[2][3];
+    float fM33 = m_aafMat[3][3];
+
+    m_afDiag[0] = fM00;
+    m_afSubd[3] = 0.0;
+
+    m_aafMat[0][0] = 1.0;
+    m_aafMat[0][1] = 0.0;
+    m_aafMat[0][2] = 0.0;
+    m_aafMat[0][3] = 0.0;
+    m_aafMat[1][0] = 0.0;
+    m_aafMat[2][0] = 0.0;
+    m_aafMat[3][0] = 0.0;
+
+    float fLength, fInvLength;
+
+    if ( fM02 != 0.0 || fM03 != 0.0 )
+    {
+        float fQ11, fQ12, fQ13;
+        float fQ21, fQ22, fQ23;
+        float fQ31, fQ32, fQ33;
+
+        // build column Q1
+        fLength = Math::sqrt(fM01*fM01 + fM02*fM02 + fM03*fM03);
+        fInvLength = 1.0/fLength;
+        fQ11 = fM01*fInvLength;
+        fQ21 = fM02*fInvLength;
+        fQ31 = fM03*fInvLength;
+
+        m_afSubd[0] = fLength;
+
+        // compute S*Q1
+        float fV0 = fM11*fQ11+fM12*fQ21+fM13*fQ31;
+        float fV1 = fM12*fQ11+fM22*fQ21+fM23*fQ31;
+        float fV2 = fM13*fQ11+fM23*fQ21+fM33*fQ31;
+
+        m_afDiag[1] = fQ11*fV0+fQ21*fV1+fQ31*fV2;
+
+        // build column Q3 = Q1x(S*Q1)
+        fQ13 = fQ21*fV2-fQ31*fV1;
+        fQ23 = fQ31*fV0-fQ11*fV2;
+        fQ33 = fQ11*fV1-fQ21*fV0;
+        fLength = Math::sqrt(fQ13*fQ13+fQ23*fQ23+fQ33*fQ33);
+        if ( fLength > 0.0 )
+        {
+            fInvLength = 1.0/fLength;
+            fQ13 *= fInvLength;
+            fQ23 *= fInvLength;
+            fQ33 *= fInvLength;
+
+            // build column Q2 = Q3xQ1
+            fQ12 = fQ23*fQ31-fQ33*fQ21;
+            fQ22 = fQ33*fQ11-fQ13*fQ31;
+            fQ32 = fQ13*fQ21-fQ23*fQ11;
+
+            fV0 = fQ12*fM11+fQ22*fM12+fQ32*fM13;
+            fV1 = fQ12*fM12+fQ22*fM22+fQ32*fM23;
+            fV2 = fQ12*fM13+fQ22*fM23+fQ32*fM33;
+            m_afSubd[1] = fQ11*fV0+fQ21*fV1+fQ31*fV2;
+            m_afDiag[2] = fQ12*fV0+fQ22*fV1+fQ32*fV2;
+            m_afSubd[2] = fQ13*fV0+fQ23*fV1+fQ33*fV2;
+
+            fV0 = fQ13*fM11+fQ23*fM12+fQ33*fM13;
+            fV1 = fQ13*fM12+fQ23*fM22+fQ33*fM23;
+            fV2 = fQ13*fM13+fQ23*fM23+fQ33*fM33;
+            m_afDiag[3] = fQ13*fV0+fQ23*fV1+fQ33*fV2;
+        }
+        else
+        {
+            // S*Q1 parallel to Q1, choose any valid Q2 and Q3
+            m_afSubd[1] = 0;
+
+            fLength = fQ21*fQ21+fQ31*fQ31;
+            if ( fLength > 0.0 )
+            {
+                fInvLength = 1.0/fLength;
+                float fTmp = fQ11-1.0;
+                fQ12 = -fQ21;
+                fQ22 = 1.0+fTmp*fQ21*fQ21*fInvLength;
+                fQ32 = fTmp*fQ21*fQ31*fInvLength;
+
+                fQ13 = -fQ31;
+                fQ23 = fQ32;
+                fQ33 = 1.0+fTmp*fQ31*fQ31*fInvLength;
+
+                fV0 = fQ12*fM11+fQ22*fM12+fQ32*fM13;
+                fV1 = fQ12*fM12+fQ22*fM22+fQ32*fM23;
+                fV2 = fQ12*fM13+fQ22*fM23+fQ32*fM33;
+                m_afDiag[2] = fQ12*fV0+fQ22*fV1+fQ32*fV2;
+                m_afSubd[2] = fQ13*fV0+fQ23*fV1+fQ33*fV2;
+
+                fV0 = fQ13*fM11+fQ23*fM12+fQ33*fM13;
+                fV1 = fQ13*fM12+fQ23*fM22+fQ33*fM23;
+                fV2 = fQ13*fM13+fQ23*fM23+fQ33*fM33;
+                m_afDiag[3] = fQ13*fV0+fQ23*fV1+fQ33*fV2;
+            }
+            else
+            {
+                // Q1 = (+-1,0,0)
+                fQ12 = 0.0; fQ22 = 1.0; fQ32 = 0.0;
+                fQ13 = 0.0; fQ23 = 0.0; fQ33 = 1.0;
+
+                m_afDiag[2] = fM22;
+                m_afDiag[3] = fM33;
+                m_afSubd[2] = fM23;
+            }
+        }
+
+        m_aafMat[1][1] = fQ11; m_aafMat[1][2] = fQ12; m_aafMat[1][3] = fQ13;
+        m_aafMat[2][1] = fQ21; m_aafMat[2][2] = fQ22; m_aafMat[2][3] = fQ23;
+        m_aafMat[3][1] = fQ31; m_aafMat[3][2] = fQ32; m_aafMat[3][3] = fQ33;
+    }
+    else
+    {
+        m_afDiag[1] = fM11;
+        m_afSubd[0] = fM01;
+        m_aafMat[1][1] = 1.0;
+        m_aafMat[2][1] = 0.0;
+        m_aafMat[3][1] = 0.0;
+
+        if ( fM13 != 0.0 )
+        {
+            fLength = Math::sqrt(fM12*fM12+fM13*fM13);
+            fInvLength = 1.0/fLength;
+            fM12 *= fInvLength;
+            fM13 *= fInvLength;
+            float fQ = 2.0*fM12*fM23+fM13*(fM33-fM22);
+
+            m_afDiag[2] = fM22+fM13*fQ;
+            m_afDiag[3] = fM33-fM13*fQ;
+            m_afSubd[1] = fLength;
+            m_afSubd[2] = fM23-fM12*fQ;
+            m_aafMat[1][2] = 0.0;
+            m_aafMat[1][3] = 0.0;
+            m_aafMat[2][2] = fM12;
+            m_aafMat[2][3] = fM13;
+            m_aafMat[3][2] = fM13;
+            m_aafMat[3][3] = -fM12;
+        }
+        else
+        {
+            m_afDiag[2] = fM22;
+            m_afDiag[3] = fM33;
+            m_afSubd[1] = fM12;
+            m_afSubd[2] = fM23;
+            m_aafMat[1][2] = 0.0;
+            m_aafMat[1][3] = 0.0;
+            m_aafMat[2][2] = 1.0;
+            m_aafMat[2][3] = 0.0;
+            m_aafMat[3][2] = 0.0;
+            m_aafMat[3][3] = 1.0;
+        }
+    }
+}
+//---------------------------------------------------------------------------
+void Eigen::TridiagonalN (int iSize, float** m_aafMat,
+    float* m_afDiag, float* m_afSubd)
+{
+    int i0, i1, i2, i3;
+
+    for (i0 = iSize-1, i3 = iSize-2; i0 >= 1; i0--, i3--)
+    {
+        float fH = 0.0, fScale = 0.0;
+
+        if ( i3 > 0 )
+        {
+            for (i2 = 0; i2 <= i3; i2++)
+                fScale += Math::abs(m_aafMat[i0][i2]);
+            if ( fScale == 0 )
+            {
+                m_afSubd[i0] = m_aafMat[i0][i3];
+            }
+            else
+            {
+                float fInvScale = 1.0/fScale;
+                for (i2 = 0; i2 <= i3; i2++)
+                {
+                    m_aafMat[i0][i2] *= fInvScale;
+                    fH += m_aafMat[i0][i2]*m_aafMat[i0][i2];
+                }
+                float fF = m_aafMat[i0][i3];
+                float fG = Math::sqrt(fH);
+                if ( fF > 0.0 )
+                    fG = -fG;
+                m_afSubd[i0] = fScale*fG;
+                fH -= fF*fG;
+                m_aafMat[i0][i3] = fF-fG;
+                fF = 0.0;
+                float fInvH = 1.0/fH;
+                for (i1 = 0; i1 <= i3; i1++)
+                {
+                    m_aafMat[i1][i0] = m_aafMat[i0][i1]*fInvH;
+                    fG = 0.0;
+                    for (i2 = 0; i2 <= i1; i2++)
+                        fG += m_aafMat[i1][i2]*m_aafMat[i0][i2];
+                    for (i2 = i1+1; i2 <= i3; i2++)
+                        fG += m_aafMat[i2][i1]*m_aafMat[i0][i2];
+                    m_afSubd[i1] = fG*fInvH;
+                    fF += m_afSubd[i1]*m_aafMat[i0][i1];
+                }
+                float fHalfFdivH = 0.5*fF*fInvH;
+                for (i1 = 0; i1 <= i3; i1++)
+                {
+                    fF = m_aafMat[i0][i1];
+                    fG = m_afSubd[i1] - fHalfFdivH*fF;
+                    m_afSubd[i1] = fG;
+                    for (i2 = 0; i2 <= i1; i2++)
+                    {
+                        m_aafMat[i1][i2] -= fF*m_afSubd[i2] +
+                            fG*m_aafMat[i0][i2];
+                    }
+                }
+            }
+        }
+        else
+        {
+            m_afSubd[i0] = m_aafMat[i0][i3];
+        }
+
+        m_afDiag[i0] = fH;
+    }
+
+    m_afDiag[0] = m_afSubd[0] = 0;
+    for (i0 = 0, i3 = -1; i0 <= iSize-1; i0++, i3++)
+    {
+        if ( m_afDiag[i0] )
+        {
+            for (i1 = 0; i1 <= i3; i1++)
+            {
+                float fSum = 0;
+                for (i2 = 0; i2 <= i3; i2++)
+                    fSum += m_aafMat[i0][i2]*m_aafMat[i2][i1];
+                for (i2 = 0; i2 <= i3; i2++)
+                    m_aafMat[i2][i1] -= fSum*m_aafMat[i2][i0];
+            }
+        }
+        m_afDiag[i0] = m_aafMat[i0][i0];
+        m_aafMat[i0][i0] = 1;
+        for (i1 = 0; i1 <= i3; i1++)
+            m_aafMat[i1][i0] = m_aafMat[i0][i1] = 0;
+    }
+
+    // re-ordering if Eigen::QLAlgorithm is used subsequently
+    for (i0 = 1, i3 = 0; i0 < iSize; i0++, i3++)
+        m_afSubd[i3] = m_afSubd[i0];
+    m_afSubd[iSize-1] = 0;
+}
+//---------------------------------------------------------------------------
+bool Eigen::QLAlgorithm (int iSize, float* m_afDiag, float* m_afSubd,
+    float** m_aafMat)
+{
+    const int iMaxIter = 32;
+
+    for (int i0 = 0; i0 < iSize; i0++)
+    {
+        int i1;
+        for (i1 = 0; i1 < iMaxIter; i1++)
+        {
+            int i2;
+            for (i2 = i0; i2 <= iSize-2; i2++)
+            {
+                float fTmp =
+                    Math::abs(m_afDiag[i2])+ Math::abs(m_afDiag[i2+1]);
+                if ( Math::abs(m_afSubd[i2]) + fTmp == fTmp )
+                    break;
+            }
+            if ( i2 == i0 )
+                break;
+
+            float fG = (m_afDiag[i0+1]-m_afDiag[i0])/(2.0*m_afSubd[i0]);
+            float fR = Math::sqrt(fG*fG+1.0);
+            if ( fG < 0.0 )
+                fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
+            else
+                fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
+            float fSin = 1.0, fCos = 1.0, fP = 0.0;
+            for (int i3 = i2-1; i3 >= i0; i3--)
+            {
+                float fF = fSin*m_afSubd[i3];
+                float fB = fCos*m_afSubd[i3];
+                if ( Math::abs(fF) >= Math::abs(fG) )
+                {
+                    fCos = fG/fF;
+                    fR = sqrt(fCos*fCos+1.0);
+                    m_afSubd[i3+1] = fF*fR;
+                    fSin = 1.0/fR;
+                    fCos *= fSin;
+                }
+                else
+                {
+                    fSin = fF/fG;
+                    fR = Math::sqrt(fSin*fSin+1.0);
+                    m_afSubd[i3+1] = fG*fR;
+                    fCos = 1.0/fR;
+                    fSin *= fCos;
+                }
+                fG = m_afDiag[i3+1]-fP;
+                fR = (m_afDiag[i3]-fG)*fSin+2.0*fB*fCos;
+                fP = fSin*fR;
+                m_afDiag[i3+1] = fG+fP;
+                fG = fCos*fR-fB;
+
+                for (int i4 = 0; i4 < iSize; i4++)
+                {
+                    fF = m_aafMat[i4][i3+1];
+                    m_aafMat[i4][i3+1] = fSin*m_aafMat[i4][i3]+fCos*fF;
+                    m_aafMat[i4][i3] = fCos*m_aafMat[i4][i3]-fSin*fF;
+                }
+            }
+            m_afDiag[i0] -= fP;
+            m_afSubd[i0] = fG;
+            m_afSubd[i2] = 0.0;
+        }
+        if ( i1 == iMaxIter )
+            return false;
+    }
+
+    return true;
+}
+//---------------------------------------------------------------------------
+void Eigen::DecreasingSort (int iSize, float* afEigval,
+    float** aafEigvec)
+{
+    // sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
+    for (int i0 = 0, i1; i0 <= iSize-2; i0++)
+    {
+        // locate maximum eigenvalue
+        i1 = i0;
+        float fMax = afEigval[i1];
+        int i2;
+        for (i2 = i0+1; i2 < iSize; i2++)
+        {
+            if ( afEigval[i2] > fMax )
+            {
+                i1 = i2;
+                fMax = afEigval[i1];
+            }
+        }
+
+        if ( i1 != i0 )
+        {
+            // swap eigenvalues
+            afEigval[i1] = afEigval[i0];
+            afEigval[i0] = fMax;
+
+            // swap eigenvectors
+            for (i2 = 0; i2 < iSize; i2++)
+            {
+                float fTmp = aafEigvec[i2][i0];
+                aafEigvec[i2][i0] = aafEigvec[i2][i1];
+                aafEigvec[i2][i1] = fTmp;
+            }
+        }
+    }
+}
+//---------------------------------------------------------------------------
+void Eigen::IncreasingSort (int iSize, float* afEigval,
+    float** aafEigvec)
+{
+    // sort eigenvalues in increasing order, e[0] <= ... <= e[iSize-1]
+    for (int i0 = 0, i1; i0 <= iSize-2; i0++)
+    {
+        // locate minimum eigenvalue
+        i1 = i0;
+        float fMin = afEigval[i1];
+        int i2;
+        for (i2 = i0+1; i2 < iSize; i2++)
+        {
+            if ( afEigval[i2] < fMin )
+            {
+                i1 = i2;
+                fMin = afEigval[i1];
+            }
+        }
+
+        if ( i1 != i0 )
+        {
+            // swap eigenvalues
+            afEigval[i1] = afEigval[i0];
+            afEigval[i0] = fMin;
+
+            // swap eigenvectors
+            for (i2 = 0; i2 < iSize; i2++)
+            {
+                float fTmp = aafEigvec[i2][i0];
+                aafEigvec[i2][i0] = aafEigvec[i2][i1];
+                aafEigvec[i2][i1] = fTmp;
+            }
+        }
+    }
+}
+//---------------------------------------------------------------------------
+void Eigen::SetMatrix (float** aafMat)
+{
+    for (int iRow = 0; iRow < m_iSize; iRow++)
+    {
+        for (int iCol = 0; iCol < m_iSize; iCol++)
+            m_aafMat[iRow][iCol] = aafMat[iRow][iCol];
+    }
+}
+//---------------------------------------------------------------------------
+void Eigen::EigenStuff2 ()
+{
+    Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::EigenStuff3 ()
+{
+    Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::EigenStuff4 ()
+{
+    Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::EigenStuffN ()
+{
+    TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::EigenStuff ()
+{
+    switch ( m_iSize )
+    {
+        case 2:
+            Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 3:
+            Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 4:
+            Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        default:
+            TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+            break;
+    }
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::DecrSortEigenStuff2 ()
+{
+    Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    DecreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::DecrSortEigenStuff3 ()
+{
+    Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    DecreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::DecrSortEigenStuff4 ()
+{
+    Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    DecreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::DecrSortEigenStuffN ()
+{
+    TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    DecreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::DecrSortEigenStuff ()
+{
+    switch ( m_iSize )
+    {
+        case 2:
+            Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 3:
+            Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 4:
+            Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        default:
+            TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+            break;
+    }
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    DecreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::IncrSortEigenStuff2 ()
+{
+    Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    IncreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::IncrSortEigenStuff3 ()
+{
+    Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    IncreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::IncrSortEigenStuff4 ()
+{
+    Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    IncreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::IncrSortEigenStuffN ()
+{
+    TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    IncreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+void Eigen::IncrSortEigenStuff ()
+{
+    switch ( m_iSize )
+    {
+        case 2:
+            Tridiagonal2(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 3:
+            Tridiagonal3(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        case 4:
+            Tridiagonal4(m_aafMat,m_afDiag,m_afSubd);
+            break;
+        default:
+            TridiagonalN(m_iSize,m_aafMat,m_afDiag,m_afSubd);
+            break;
+    }
+    QLAlgorithm(m_iSize,m_afDiag,m_afSubd,m_aafMat);
+    IncreasingSort(m_iSize,m_afDiag,m_aafMat);
+}
+//---------------------------------------------------------------------------
+
+};
+
+
+/*
+#ifdef EIGEN_TEST
+
+int main ()
+{
+    Eigen kES(3);
+
+    kES.Matrix(0,0) = 2.0;  kES.Matrix(0,1) = 1.0;  kES.Matrix(0,2) = 1.0;
+    kES.Matrix(1,0) = 1.0;  kES.Matrix(1,1) = 2.0;  kES.Matrix(1,2) = 1.0;
+    kES.Matrix(2,0) = 1.0;  kES.Matrix(2,1) = 1.0;  kES.Matrix(2,2) = 2.0;
+
+    kES.IncrSortEigenStuff3();
+
+    cout.setf(ios::fixed);
+
+    cout << "eigenvalues = " << endl;
+    int iRow;
+    for (iRow = 0; iRow < 3; iRow++)
+        cout << kES.GetEigenvalue(iRow) << ' ';
+    cout << endl;
+
+    cout << "eigenvectors = " << endl;
+    for (iRow = 0; iRow < 3; iRow++)
+    {
+        for (int iCol = 0; iCol < 3; iCol++)
+            cout << kES.GetEigenvector(iRow,iCol) << ' ';
+        cout << endl;
+    }
+
+    // eigenvalues =
+    //    1.000000 1.000000 4.000000
+    // eigenvectors =
+    //    0.411953  0.704955 0.577350
+    //    0.404533 -0.709239 0.577350
+    //   -0.816485  0.004284 0.577350
+
+    return 0;
+}
+
+#endif
+*/
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/OOBox.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/OOBox.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/OOBox.h	(revision 4)
@@ -0,0 +1,211 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          OOBox.h,v
+ * Date modified: 2002/05/20 22:39:22
+ * Version:       1.5
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_OOBox_H_
+#define _GMTL_OOBox_H_
+
+#include <gmtl/Vec3.h>
+#include <gmtl/Point3.h>
+#include <gmtl/matVecFuncs.h>
+
+namespace gmtl
+{
+
+// AABox : Defines an object aligned box
+//
+// For definition of an OOB, see pg 293-294 of Real-Time Rendering
+class  OOBox
+{
+
+public:
+   OOBox()
+   { ident(); }
+
+   OOBox(OOBox& box);
+
+public:
+   // Accessors
+   Point3& center();
+   const Point3& center() const;
+
+   Vec3& axis (int i);
+   const Vec3& axis (int i) const;
+   Vec3* axes ();
+   const Vec3* axes () const;
+
+   float& halfLen(int i);
+   const float& halfLen(int i) const;
+   float* halfLens();
+   const float* halfLens() const;
+
+   // Assignment
+   OOBox& operator=(const OOBox& box);
+
+   // Comparison
+   bool operator==(const OOBox& box) const;
+
+   //  return the verts that define the box
+   // Order: XYZ: 000, 100, 110, 010,
+   //             001, 101, 111, 011
+   void getVerts(Point3 verts[8]) const;
+
+   // Merge current box with other box to get new box covering both
+   void mergeWith(const OOBox& box);
+
+   void ident()
+   {
+      mCenter = ZeroVec3;
+      mAxis[0] = XUnitVec3;
+      mAxis[1] = YUnitVec3;
+      mAxis[2] = ZUnitVec3;
+      mHalfLen[0] = mHalfLen[1] = mHalfLen[2] = 0.0f;
+   }
+
+public:
+   Point3  mCenter;     // The center point of the box
+   Vec3    mAxis[3];    // The axes of the oriented box (xAxis, yAxis, zAxis)
+   float   mHalfLen[3]; // Half lengths of the box  ASSERT: HalfLens >= 0.0f
+};
+
+
+// ------------------------------------------------- //
+// --------------- Member definitions -------------- //
+// ------------------------------------------------- //
+inline
+OOBox::OOBox(OOBox& box)
+{
+   mCenter = box.mCenter;
+   mAxis[0] = box.mAxis[0];
+   mAxis[1] = box.mAxis[1];
+   mAxis[2] = box.mAxis[2];
+   mHalfLen[0] = box.mHalfLen[0];
+   mHalfLen[1] = box.mHalfLen[1];
+   mHalfLen[2] = box.mHalfLen[2];
+}
+
+// Accessors
+inline Point3& OOBox::center()
+{
+   return mCenter;
+}
+
+inline const Point3& OOBox::center() const
+{
+   return mCenter;
+}
+
+inline Vec3& OOBox::axis (int i)
+{
+   return mAxis[i];
+}
+
+inline const Vec3& OOBox::axis (int i) const
+{
+   return mAxis[i];
+}
+
+inline Vec3* OOBox::axes ()
+{
+   return mAxis;
+}
+
+inline const Vec3* OOBox::axes () const
+{
+   return mAxis;
+}
+
+inline float& OOBox::halfLen(int i)
+{
+   return mHalfLen[i];
+}
+
+inline const float& OOBox::halfLen(int i) const
+{
+   return mHalfLen[i];
+}
+
+inline float* OOBox::halfLens()
+{
+   return mHalfLen;
+}
+
+inline const float* OOBox::halfLens() const
+{
+   return mHalfLen;
+}
+
+// Assignment
+inline OOBox& OOBox::operator=(const OOBox& box)
+{
+   mCenter = box.mCenter;
+   mAxis[0] = box.mAxis[0];
+   mAxis[1] = box.mAxis[1];
+   mAxis[2] = box.mAxis[2];
+   mHalfLen[0] = box.mHalfLen[0];
+   mHalfLen[1] = box.mHalfLen[1];
+   mHalfLen[2] = box.mHalfLen[2];
+   return *this;
+}
+
+// Comparison
+inline bool OOBox::operator==(const OOBox& box) const
+{
+   return ((mCenter == box.mCenter) &&
+           (mAxis[0] == box.mAxis[0]) &&
+           (mAxis[1] == box.mAxis[1]) &&
+           (mAxis[2] == box.mAxis[2]) &&
+           (mHalfLen[0] == box.mHalfLen[0]) &&
+           (mHalfLen[1] == box.mHalfLen[1]) &&
+           (mHalfLen[2] == box.mHalfLen[2]));
+}
+
+inline void OOBox::getVerts(Point3 verts[8]) const
+{
+   Vec3 x_half_axis = mAxis[0]*mHalfLen[0];
+   Vec3 y_half_axis = mAxis[1]*mHalfLen[1];
+   Vec3 z_half_axis = mAxis[2]*mHalfLen[2];
+
+   verts[0] = mCenter - x_half_axis - y_half_axis - z_half_axis;
+   verts[1] = mCenter + x_half_axis - y_half_axis - z_half_axis;
+   verts[2] = mCenter + x_half_axis + y_half_axis - z_half_axis;
+   verts[3] = mCenter - x_half_axis + y_half_axis - z_half_axis;
+   verts[4] = mCenter - x_half_axis - y_half_axis + z_half_axis;
+   verts[5] = mCenter + x_half_axis - y_half_axis + z_half_axis;
+   verts[6] = mCenter + x_half_axis + y_half_axis + z_half_axis;
+   verts[7] = mCenter - x_half_axis + y_half_axis + z_half_axis;
+}
+
+};
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Output.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Output.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Output.h	(revision 4)
@@ -0,0 +1,331 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Output.h,v
+ * Date modified: 2005/05/12 21:42:10
+ * Version:       1.17
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_OUTPUT_H_
+#define _GMTL_OUTPUT_H_
+
+#include <iostream>
+#include <gmtl/Util/Assert.h>
+#include <gmtl/VecBase.h>
+#include <gmtl/Matrix.h>
+#include <gmtl/Quat.h>
+#include <gmtl/Tri.h>
+#include <gmtl/Plane.h>
+#include <gmtl/Sphere.h>
+#include <gmtl/EulerAngle.h>
+#include <gmtl/AABox.h>
+#include <gmtl/Ray.h>
+#include <gmtl/LineSeg.h>
+#include <gmtl/Coord.h>
+
+namespace gmtl
+{
+   namespace output
+   {
+      /** Outputters for vector types. */
+#ifndef GMTL_NO_METAPROG
+      template<typename DATA_TYPE, unsigned SIZE, typename REP>
+      struct VecOutputter
+      {
+         static std::ostream& outStream(std::ostream& out, const VecBase<DATA_TYPE,SIZE,REP>& v)
+         {
+            VecBase<DATA_TYPE,SIZE, gmtl::meta::DefaultVecTag> temp_vec(v);
+            VecOutputter<DATA_TYPE,SIZE,gmtl::meta::DefaultVecTag>::outStream(out,v);
+            return out;
+         }
+      };
+
+      template<typename DATA_TYPE, unsigned SIZE>
+      struct VecOutputter<DATA_TYPE,SIZE,gmtl::meta::DefaultVecTag>
+      {
+         static std::ostream& outStream(std::ostream& out, const VecBase<DATA_TYPE,SIZE,gmtl::meta::DefaultVecTag>& v)
+         {
+            out << "(";
+            for ( unsigned i=0; i<SIZE; ++i )
+            {
+               if ( i != 0 )
+               {
+                  out << ", ";
+               }
+               out << v[i];
+            }
+            out << ")";
+            return out;
+         }
+      };
+#endif
+   }
+
+   /** @ingroup Output
+    *  @name Output Stream Operators
+    */
+   //@{
+   /**
+    * Outputs a string representation of the given VecBase type to the given
+    * output stream. This works for both Point and Vec types. The output is
+    * formatted such that Vec<int, 4>(1,2,3,4) will appear as "(1, 2, 3, 4)".
+    *
+    * @param out     the stream to write to
+    * @param v       the VecBase type to output
+    *
+    * @return  out after it has been written to
+    */
+#ifdef GMTL_NO_METAPROG
+   template<typename DATA_TYPE, unsigned SIZE>
+   std::ostream& operator<<(std::ostream& out, const VecBase<DATA_TYPE, SIZE>& v)
+   {
+      out << "(";
+      for ( unsigned i=0; i<SIZE; ++i )
+      {
+         if ( i != 0 )
+         {
+            out << ", ";
+         }
+         out << v[i];
+      }
+      out << ")";
+      return out;
+   }
+#else
+   template<typename DATA_TYPE, unsigned SIZE, typename REP>
+   std::ostream& operator<<(std::ostream& out, const VecBase<DATA_TYPE, SIZE, REP>& v)
+   {
+      return output::VecOutputter<DATA_TYPE,SIZE,REP>::outStream(out,v);
+   }
+#endif
+
+   /**
+    * Outputs a string representation of the given EulerAngle type to the given
+    * output stream.  Format is {ang1,ang2,ang3}
+    *
+    * @param out     the stream to write to
+    * @param e       the EulerAngle type to output
+    *
+    * @return  out after it has been written to
+    */
+   template< class DATA_TYPE, typename ROTATION_ORDER>
+   std::ostream& operator<<( std::ostream& out,
+                             const EulerAngle<DATA_TYPE, ROTATION_ORDER>& e )
+   {
+      const DATA_TYPE* angle_data(e.getData());
+      out << "{" << angle_data[0] << ", " << angle_data[1] << ", " << angle_data[2] << "}";
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Matrix to the given output
+    * stream. The output is formatted along the lines of:
+    * <pre>
+    *    | 1 2 3 4 |
+    *    | 5 6 7 8 |
+    *    | 9 10 11 12 |
+    * </pre>
+    *
+    * @param out     the stream to write to
+    * @param m       the Matrix to output
+    *
+    * @return  out after it has been written to
+    */
+   template< class DATA_TYPE, unsigned ROWS, unsigned COLS >
+   std::ostream& operator<<( std::ostream& out,
+                             const Matrix<DATA_TYPE, ROWS, COLS>& m )
+   {
+      for ( unsigned row=0; row<ROWS; ++row )
+      {
+         out << "|";
+         for ( unsigned col=0; col<COLS; ++col )
+         {
+            out << " " << m(row, col);
+         }
+         out << " |" << std::endl;
+      }
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Matrix to the given output
+    * stream. The output is formatted such that Quat<int>(1,2,3,4) will appear
+    * as "(1, 2, 3, 4)".
+    *
+    * @param out     the stream to write to
+    * @param q       the Quat to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const Quat<DATA_TYPE>& q )
+   {
+      out << q.mData;
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Tri to the given output
+    * stream. The output is formatted such that
+    *    Tri<int>(
+    *       Point<int, 3>(1,2,3),
+    *       Point<int, 3>(4,5,6),
+    *       Point<int, 3>(7,8,9)
+    *    )
+    * will appear as "(1, 2, 3), (4, 5, 6), (7, 8, 9)".
+    *
+    * @param out     the stream to write to
+    * @param t       the Tri to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const Tri<DATA_TYPE> &t )
+   {
+      out << t[0] << ", " << t[1] << ", " << t[2];
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Plane to the given output
+    * stream. The output is formatted such that
+    *    Plane<int>(
+    *       Vec<int, 3>(1,2,3),
+    *       4
+    *    )
+    * will appear as "(1, 2, 3), 4)".
+    *
+    * @param out     the stream to write to
+    * @param p       the Plane to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const Plane<DATA_TYPE> &p )
+   {
+      out << p.mNorm << ", " << p.mOffset;
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Sphere to the given output
+    * stream. The output is formatted such that
+    *    Sphere<int>(
+    *       Point<int, 3>(1,2,3),
+    *       4
+    *    )
+    * will appear as "(1, 2, 3), 4)".
+    *
+    * @param out     the stream to write to
+    * @param s       the Sphere to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const Sphere<DATA_TYPE> &s )
+   {
+      out << s.mCenter << ", " << s.mRadius;
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given AABox to the given output
+    * stream. The output is formatted such that
+    *    AABox<int>(
+    *       Point<int, 3>(1,2,3),
+    *       Point<int, 3>(4,5,6)
+    *    )
+    * will appear as "(1,2,3) (4,5,6) false".
+    *
+    * @param out     the stream to write to
+    * @param b       the AABox to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const AABox<DATA_TYPE>& b)
+   {
+      out << b.mMin << " " << b.mMax << " ";
+      out << (b.mEmpty ? "true" : "false");
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given Ray to the given output
+    * stream. The output is formatted such that
+    *    Ray<int>(
+    *       Point<int>(1,2,3),
+    *       Vec<int>(4,5,6)
+    *    )
+    * will appear as "(1,2,3) (4,5,6)".
+    *
+    * @param out     the stream to write to
+    * @param b       the Ray to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const Ray<DATA_TYPE>& b )
+   {
+      out << b.getOrigin() << " " << b.getDir();
+      return out;
+   }
+
+   /**
+    * Outputs a string representation of the given LineSeg to the given output
+    * stream. The output is formatted such that
+    *    LineSeg<int>(
+    *       Point<int>(1,2,3),
+    *       Vec<int>(4,5,6)
+    *    )
+    * will appear as "(1,2,3) (4,5,6)".
+    *
+    * @param out     the stream to write to
+    * @param b       the LineSeg to output
+    *
+    * @return  out after it has been written to
+    */
+   template< typename DATA_TYPE >
+   std::ostream& operator<<( std::ostream& out, const LineSeg<DATA_TYPE>& b )
+   {
+      out << b.getOrigin() << " " << b.getDir();
+      return out;
+   }
+
+   template< typename POS_TYPE, typename ROT_TYPE>
+   std::ostream& operator<<( std::ostream& out, const Coord<POS_TYPE,ROT_TYPE>& c)
+   {
+      out << "p:" << c.getPos() << " r:" << c.getRot();
+      return out;
+   }
+   //@}
+
+} // end namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Plane.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Plane.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Plane.h	(revision 4)
@@ -0,0 +1,255 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Plane.h,v
+ * Date modified: 2003/04/18 22:55:21
+ * Version:       1.14
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_PLANE_H
+#define _GMTL_PLANE_H
+
+#include <gmtl/Vec.h>
+#include <gmtl/Point.h>
+#include <gmtl/VecOps.h>
+
+namespace gmtl
+{
+
+/**
+ *  Plane: Defines a geometrical plane.
+ *
+ *  All points on the plane satify the equation dot(Pt,Normal) = offset
+ *  normal is assumed to be normalized
+ *
+ *  NOTE: Some plane implementation store D instead of offset.  Thus
+ *       those implementation have opposite sign from what we have
+ *
+ * pg. 309 Computer Graphics 2nd Edition Hearn Baker
+ *<pre>
+ *  N dot P = -D
+ *   |
+ *   |-d-|
+ * __|___|-->N
+ *   |   |
+ *</pre>
+ * @ingroup Types
+ */
+template< class DATA_TYPE>
+class Plane
+{
+public:
+   /**
+    * Creates an uninitialized Plane. In other words, the normal is (0,0,0) and
+    * the offset is 0.
+    */
+   Plane()
+      : mOffset( 0 )
+   {}
+
+   /**
+    * Creates a plane that the given points lie on.
+    *
+    * @param pt1     a point on the plane
+    * @param pt2     a point on the plane
+    * @param pt3     a point on the plane
+    */
+   Plane( const Point<DATA_TYPE, 3>& pt1, const Point<DATA_TYPE, 3>& pt2,
+          const Point<DATA_TYPE, 3>& pt3)
+   {
+      Vec<DATA_TYPE, 3> vec12( pt2-pt1 );
+      Vec<DATA_TYPE, 3> vec13( pt3-pt1 );
+
+      cross( mNorm, vec12, vec13 );
+      normalize( mNorm );
+
+      mOffset = dot( static_cast< Vec<DATA_TYPE, 3> >(pt1), mNorm );  // Graphics Gems I: Page 390
+   }
+
+   /**
+    * Creates a plane with the given normal on which pt resides.
+    *
+    * @param norm    the normal of the plane
+    * @param pt      a point that lies on the plane
+    */
+   Plane( const Vec<DATA_TYPE, 3>& norm, const Point<DATA_TYPE, 3>& pt )
+      : mNorm( norm )
+   {
+      mOffset = dot( static_cast< Vec<DATA_TYPE, 3> >(pt), norm );
+   }
+
+   /**
+    * Creates a plane with the given normal and offset.
+    *
+    * @param norm          the normal of the plane
+    * @param dPlaneConst   the plane offset constant
+    */
+   Plane( const Vec<DATA_TYPE, 3>& norm, const DATA_TYPE& dPlaneConst )
+      : mNorm( norm ), mOffset( dPlaneConst )
+   {}
+
+   /**
+    * Creates an exact duplicate of the given plane.
+    *
+    * @param plane   the plane to copy
+    */
+   Plane( const Plane<DATA_TYPE>& plane )
+      : mNorm( plane.mNorm ), mOffset( plane.mOffset )
+   {}
+
+   /**
+    * Gets the normal for this plane.
+    *
+    * @return  this plane's normal vector
+    */
+   const Vec<DATA_TYPE, 3>& getNormal() const
+   {
+      return mNorm;
+   }
+
+   /**
+    * Sets the normal for this plane to the given vector.
+    *
+    * @param norm    the new normalized vector
+    *
+    * @pre |norm| = 1
+    */
+   void setNormal( const Vec<DATA_TYPE, 3>& norm )
+   {
+      mNorm = norm;
+   }
+
+   /**
+    * Gets the offset of this plane from the origin such that the offset is the
+    * negative distance from the origin.
+    *
+    * @return  this plane's offset
+    */
+   const DATA_TYPE& getOffset() const
+   {
+      return mOffset;
+   }
+
+   /**
+    * Sets the offset of this plane from the origin.
+    *
+    * @param offset     the new offset
+    */
+   void setOffset( const DATA_TYPE& offset )
+   {
+      mOffset = offset;
+   }
+
+public:
+   // dot(Pt,mNorm) = mOffset
+   /**
+    * The normal for this vector. For any point on the plane,
+    * dot( pt, mNorm) = mOffset.
+    */
+   Vec<DATA_TYPE, 3> mNorm;
+
+   /**
+    * This plane's offset from the origin such that for any point pt,
+    * dot( pt, mNorm ) = mOffset. Note that mOffset = -D (neg dist from the
+    * origin).
+    */
+   DATA_TYPE mOffset;
+};
+
+typedef Plane<float> Planef;
+typedef Plane<double> Planed;
+
+/*
+#include <geomdist.h>
+
+
+// Intersects the plane with a given segment.
+// Returns TRUE if there is a hit (within the seg).
+// Also returns the distance "down" the segment of the hit in t.
+//
+// PRE: seg.dir must be normalized
+//
+int sgPlane::isect(sgSeg& seg, float* t)
+{
+	// Graphic Gems I: Page 391
+	float denom = normal.dot(seg.dir);
+	if (SG_IS_ZERO(denom))		// No Hit
+	{
+		//: So now, it is just dist to plane tested against length
+		sgVec3	hit_pt;
+		float		hit_dist;		// Dist to hit
+		
+		hit_dist = findNearestPt(seg.pos, hit_pt);
+		*t = hit_dist;			// Since dir is normalized
+
+		if(seg.tValueOnSeg(*t))
+			return 1;
+		else
+			return 0;
+	}
+	else
+	{
+		float numer = offset + normal.dot(seg.pos);
+		(*t) = -1.0f * (numer/denom);
+		
+		if(seg.tValueOnSeg(*t))
+			return 1;
+		else
+			return 0;
+	}
+}
+
+///
+ // Intersects the plane with the line defined
+ // by the given segment
+ //
+ // seg - seg that represents the line to isect
+ // t   - the t value of the isect
+ //
+int sgPlane::isectLine(const sgSeg& seg, float* t)
+{
+	// GGI: Pg 299
+	// Lu = seg.pos;
+	// Lv = seg.dir;
+	// Jn = normal;
+	// Jd = offset;
+	
+	float denom = normal.dot(seg.dir);
+	if(denom == 0.0f)
+      return 0;
+	else
+	{
+      *t = - (offset+ normal.dot(seg.pos))/(denom);
+      return 1;
+	}
+}
+*/
+
+} // namespace gmtl
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/PlaneOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/PlaneOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/PlaneOps.h	(revision 4)
@@ -0,0 +1,213 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          PlaneOps.h,v
+ * Date modified: 2005/06/04 18:40:46
+ * Version:       1.13
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_PLANEOPS_H_
+#define _GMTL_PLANEOPS_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Plane.h>
+#include <gmtl/Math.h>
+
+namespace gmtl
+{
+
+/** @ingroup Ops Plane 
+ * @name Plane Operations
+ * @{
+ */
+       
+/**
+ * Computes the distance from the plane to the point.
+ *
+ * @param plane      the plane to compare the point to it
+ * @param pt         a point in space
+ *
+ * @return  the distance from the point to the plane
+ */
+template< class DATA_TYPE >
+DATA_TYPE distance( const Plane<DATA_TYPE>& plane, const Point<DATA_TYPE, 3>& pt )
+{
+   return ( dot(plane.mNorm, static_cast< Vec<DATA_TYPE, 3> >(pt)) - plane.mOffset );
+}
+
+/**
+ * Determines which side of the plane the given point lies. This operation is
+ * done with ZERO tolerance.
+ *
+ * @param plane      the plane to compare the point to
+ * @param pt         the point to test
+ *
+ * @return  the PlaneSide enum describing on which side of the plane the point
+ *          lies
+ */
+template< class DATA_TYPE >
+PlaneSide whichSide( const Plane<DATA_TYPE>& plane,
+                     const Point<DATA_TYPE, 3>& pt )
+{
+   DATA_TYPE dist = distance( plane, pt );
+
+   if ( dist < DATA_TYPE(0) )
+      return NEG_SIDE;
+   else if ( dist > DATA_TYPE(0) )
+      return POS_SIDE;
+   else
+      return ON_PLANE;
+}
+
+/**
+ * Determines which side of the plane the given point lies with the given
+ * epsilon tolerance.
+ *
+ * @param plane      the plane to compare the point to
+ * @param pt         the point to test
+ * @param eps        the epsilon tolerance to use while testing
+ *
+ * @return  the PlaneSide enum describing on which side of the plane the point
+ *          lies
+ */
+template< class DATA_TYPE >
+PlaneSide whichSide( const Plane<DATA_TYPE>& plane,
+                     const Point<DATA_TYPE, 3>& pt,
+                     const DATA_TYPE& eps )
+{
+   DATA_TYPE dist = distance( plane, pt );
+
+   if ( dist < eps )
+      return NEG_SIDE;
+   else if ( dist > eps )
+      return POS_SIDE;
+   else
+      return ON_PLANE;
+}
+
+/**
+ * Finds the point on the plane that is nearest to the given point. As a
+ * convenience, the distance between pt and result is returned.
+ *
+ * @param plane  [in]   the plane to compare the point to
+ * @param pt     [in]   the point to test
+ * @param result [out]  the point on plane closest to pt
+ *
+ * @return  the distance between pt and result
+ */
+template< class DATA_TYPE >
+DATA_TYPE findNearestPt( const Plane<DATA_TYPE>& plane,
+                         const Point<DATA_TYPE, 3>& pt,
+                         Point<DATA_TYPE, 3>& result )
+{
+   // GGI:  p297
+   // GGII: p223
+   gmtlASSERT( isNormalized(plane.mNorm) );   // Assert: Normalized
+   DATA_TYPE dist_to_plane(0);
+   dist_to_plane = plane.mOffset + dot( plane.mNorm, static_cast< Vec<DATA_TYPE, 3> >(pt) );
+   result = pt - (plane.mNorm * dist_to_plane);
+   return dist_to_plane;
+}
+
+/**
+ * Mirror the point by the plane
+ */
+template< class DATA_TYPE, unsigned SIZE>
+void reflect( Point<DATA_TYPE, SIZE>& result,
+              const Plane<DATA_TYPE>& plane,
+              const Point<DATA_TYPE, SIZE>& point )
+{
+   gmtl::Point<DATA_TYPE, SIZE> point_on_plane;
+   findNearestPt( plane, point, point_on_plane );
+   gmtl::Vec<DATA_TYPE, SIZE> dir = point_on_plane - point;
+   result = point + (dir * DATA_TYPE(2.0f));
+}
+/** @} */
+
+/** @ingroup Compare Plane
+ * @name Plane Comparitors
+ * @{
+ */
+
+/**
+ * Compare two planes to see if they are EXACTLY the same. In other words, this
+ * comparison is done with zero tolerance.
+ *
+ * @param p1      the first plane to compare
+ * @param p2      the second plane to compare
+ *
+ * @return  true if they are equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator==( const Plane<DATA_TYPE>& p1, const Plane<DATA_TYPE>& p2 )
+{
+   return ( (p1.mNorm == p2.mNorm) && (p1.mOffset == p2.mOffset) );
+}
+
+/**
+ * Compare two planes to see if they are not EXACTLY the same. In other words,
+ * this comparison is done with zero tolerance.
+ *
+ * @param p1      the first plane to compare
+ * @param p2      the second plane to compare
+ *
+ * @return  true if they are not equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator!=( const Plane<DATA_TYPE>& p1, const Plane<DATA_TYPE>& p2 )
+{
+   return (! (p1 == p2));
+}
+
+/**
+ * Compare two planes to see if they are the same within the given tolerance.
+ *
+ * @param p1      the first plane to compare
+ * @param p2      the second plane to compare
+ * @param eps     the tolerance value to use
+ *
+ * @pre eps must be >= 0
+ *
+ * @return  true if they are equal within a tolerance, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool isEqual( const Plane<DATA_TYPE>& p1, const Plane<DATA_TYPE>& p2,
+                     const DATA_TYPE& eps )
+{
+   gmtlASSERT( eps >= 0 );
+   return ( (isEqual(p1.mNorm, p2.mNorm, eps)) &&
+            (Math::isEqual(p1.mOffset, p2.mOffset, eps)) );
+}
+/** @} */
+
+
+} // namespace gmtl
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Point.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Point.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Point.h	(revision 4)
@@ -0,0 +1,163 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Point.h,v
+ * Date modified: 2004/10/30 18:24:33
+ * Version:       1.18
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_POINT_H_
+#define _GMTL_POINT_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/VecBase.h>
+
+namespace gmtl
+{
+
+/** Point
+ *  Use points when you need to represent a position.  Don't use points to
+ *  represent a Vector.  One difference you should note is that
+ *  ceratain matrix operations are different between Point and Vec such as
+ *  xform and operator*.  A Vec xform by matrix is simply a rotation,
+ *  while a Point xformed by a matrix is a full matrix transform
+ *  (rotation, skew, translation, scale).
+ *
+ * @see Point3f
+ * @see Point4f
+ * @see Point3d
+ * @see Point4f
+ * @ingroup Types
+ */
+template<class DATA_TYPE, unsigned SIZE>
+class Point : public VecBase<DATA_TYPE, SIZE>
+{
+public:
+   typedef DATA_TYPE DataType;
+   enum Params { Size = SIZE };
+
+   /** Placeholder for the base type */
+   typedef VecBase<DATA_TYPE, SIZE> BaseType;
+   typedef Point<DATA_TYPE, SIZE> VecType;
+
+public:
+   /** Default constructor
+    */
+   Point()
+   {
+      for (unsigned i = 0; i < SIZE; ++i)
+         this->mData[i] = (DATA_TYPE)0;
+   }
+
+   /** @name Value constructors
+    * Construct with copy of rVec
+    */
+   //@{
+   /*
+   Point(const Point<DATA_TYPE, SIZE>& rVec)
+      : BaseType(static_cast<BaseType>(rVec))
+   {;}
+   */
+
+#ifdef GMTL_NO_METAPROG
+   Point(const VecBase<DATA_TYPE, SIZE>& rVec)
+      : BaseType(rVec)
+   {;}
+#else
+   template<typename REP2>
+   Point( const VecBase<DATA_TYPE, SIZE, REP2>& rVec )
+      : BaseType( rVec )
+   {
+   }
+#endif
+
+   /**
+    * Construct a 2-D point with 2 given values
+    */
+   Point(const DATA_TYPE& val0,const DATA_TYPE& val1)
+   : BaseType(val0, val1)
+   {
+      // @todo need compile time assert
+      gmtlASSERT( SIZE == 2 && "out of bounds element access in Point" );
+   }
+
+   /**
+    * Construct a 3-D point with 2 given values
+    */
+   Point(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2)
+   : BaseType(val0, val1, val2)
+   {
+      // @todo need compile time assert
+      gmtlASSERT( SIZE == 3 && "out of bounds element access in Point" );
+   }
+
+   /**
+    * Construct a 4-D point with 2 given values
+    */
+   Point(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2,const DATA_TYPE& val3)
+   : BaseType(val0, val1, val2, val3)
+   {
+      // @todo need compile time assert
+      gmtlASSERT( SIZE == 4 && "out of bounds element access in Point" );
+   }
+   //@}
+
+   /** Assign from different rep. */
+#ifdef GMTL_NO_METAPROG
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE>& rhs)
+   {
+      BaseType::operator=(rhs);
+      return *this;
+   }
+#else
+   template<typename REP2>
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE,REP2>& rhs)
+   {
+      BaseType::operator=(rhs);
+      return *this;
+   }
+#endif
+
+};
+
+// --- helper types --- //
+typedef Point<int,2> Point2i;
+typedef Point<float,2> Point2f;
+typedef Point<double,2> Point2d;
+typedef Point<int, 3> Point3i;
+typedef Point<float,3> Point3f;
+typedef Point<double,3> Point3d;
+typedef Point<int, 4> Point4i;
+typedef Point<float,4> Point4f;
+typedef Point<double,4> Point4d;
+
+
+};
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Quat.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Quat.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Quat.h	(revision 4)
@@ -0,0 +1,189 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Quat.h,v
+ * Date modified: 2005/06/06 15:36:03
+ * Version:       1.25
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_QUAT_H_
+#define _GMTL_QUAT_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Vec.h>
+ 
+namespace gmtl
+{
+
+/** Quat: Class to encapsulate quaternion behaviors.
+ *
+ * this Quaternion is ordered in memory: x,y,z,w.
+ * @see Quatf 
+ * @see Quatd
+ *
+ * Note: The code for most of these routines was built using the following
+ * references
+ * 
+ * References:
+ * <ul>
+ * <li>   Advanced Animation and Rendering Techniques: pp363-365
+ * <li>   Animating Rotation with Quaternion Curves,  Ken Shoemake,
+ *           SIGGRAPH Proceedings Vol 19, Number 3, 1985
+ * <li>   Quaternion Calculus for Animation,  Ken Shoemake SIGGRAPH course
+ *           notes 1989
+ * <li>   Game Developer Magazine: Feb 98, pg.34-42
+ * <li>   Motivation for the use of Quaternions to perform transformations
+ *           http://www.rust.net/~kgeoinfo/quat1.htm
+ * <li>   On quaternions; or on a new system of imaginaries in algebra,
+ *           Sir William Rowan Hamilton, Philosophical Magazine, xxv,
+ *           pp. 10-13 (July 1844)
+ * <li>   You also can find more on quaternions at
+ *    <ul>
+ *    <li>  http://www.gamasutra.com/features/19980703/quaternions_01.htm and at
+ *    <li>  http://archive.ncsa.uiuc.edu/VEG/VPS/emtc/quaternions/index.html
+ *    </ul>
+ * <li>   Or search on google....
+ * </ul>
+ * @ingroup Types
+ */
+template <typename DATA_TYPE>
+class Quat
+{
+public:
+   /** use this to declare single value types of the same type as this matrix.
+    */
+   typedef DATA_TYPE DataType;
+
+   enum Params { Size = 4 };
+
+   /** default constructor, initializes to quaternion multiplication identity
+    *  [x,y,z,w] == [0,0,0,1].
+    *  NOTE: the addition identity is [0,0,0,0]
+    */
+   Quat()
+      : mData( (DATA_TYPE)0.0, (DATA_TYPE)0.0, (DATA_TYPE)0.0, (DATA_TYPE)1.0 )
+   {
+   }
+   
+   /** data constructor, initializes to quaternion multiplication identity
+    *  [x,y,z,w] == [0,0,0,1].
+    *  NOTE: the addition identity is [0,0,0,0]
+    */
+   Quat( const DATA_TYPE& x, const DATA_TYPE& y, const DATA_TYPE& z,
+         const DATA_TYPE& w )
+      : mData( x, y, z, w )
+   {
+   }
+
+   /** copy constructor
+    */
+   Quat( const Quat<DATA_TYPE>& q ) : mData( q.mData )
+   {
+   }
+
+   /** directly set the quaternion's values
+    *  @pre x,y,z,w should be normalized
+    *  @post the quaternion is set with the given values
+    */
+   void set( const DATA_TYPE x, const DATA_TYPE y, const DATA_TYPE z, const DATA_TYPE w )
+   {
+      mData.set( x, y, z, w );
+   }
+
+   /** get the raw data elements of the quaternion.
+    *  @post sets the given variables to the quaternion's x, y, z, and w values
+    */
+   void get( DATA_TYPE& x, DATA_TYPE& y, DATA_TYPE& z, DATA_TYPE& w ) const
+   {
+      x = mData[Xelt];
+      y = mData[Yelt];
+      z = mData[Zelt];
+      w = mData[Welt];
+   }
+
+   /** bracket operator.
+    *  raw data accessor.
+    *
+    * <h3> "Example (access raw data element in a Quat):" </h3>
+    * \code
+    *    Quatf q;
+    *    q[Xelt] = 0.001231176f;
+    *    q[Yelt] = 0.1222f;
+    *    q[Zelt] = 0.721f;
+    *    q[Welt] = 0.982323f;
+    * \endcode
+    *
+    * @see VectorIndex
+    */
+   DATA_TYPE& operator[]( const int x )
+   {
+      gmtlASSERT( x >= 0 && x < 4 && "out of bounds error" );
+      return mData[x];
+   }
+
+   /** bracket operator  (const version).
+    * raw data accessor.
+    *
+    * <h3> "Example (access raw data element in a Quat):" </h3>
+    * \code
+    *    Quatf q;
+    *    float rads = acos( q[Welt] ) / 2.0f;
+    * \endcode
+    *
+    * @see VectorIndex
+    */
+   const DATA_TYPE& operator[]( const int x ) const
+   {
+      gmtlASSERT( x >= 0 && x < 4 && "out of bounds error" );
+      return mData[x];
+   }
+
+   /** Get a DATA_TYPE pointer to the quat internal data.
+    * @post Returns a ptr to the head of the quat data
+    */
+   const DATA_TYPE*  getData() const { return (DATA_TYPE*)mData.getData();}
+
+public:
+   // Order x, y, z, w
+   Vec<DATA_TYPE, 4> mData;
+};
+
+const Quat<float> QUAT_MULT_IDENTITYF( 0.0f, 0.0f, 0.0f, 1.0f );
+const Quat<float> QUAT_ADD_IDENTITYF( 0.0f, 0.0f, 0.0f, 0.0f );
+const Quat<float> QUAT_IDENTITYF( QUAT_MULT_IDENTITYF );
+const Quat<double> QUAT_MULT_IDENTITYD( 0.0, 0.0, 0.0, 1.0 );
+const Quat<double> QUAT_ADD_IDENTITYD( 0.0, 0.0, 0.0, 0.0 );
+const Quat<double> QUAT_IDENTITYD( QUAT_MULT_IDENTITYD );
+
+typedef Quat<float> Quatf;
+typedef Quat<double> Quatd;
+
+} // end of namespace gmtl
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/QuatOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/QuatOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/QuatOps.h	(revision 4)
@@ -0,0 +1,670 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          QuatOps.h,v
+ * Date modified: 2004/05/25 16:36:28
+ * Version:       1.26
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_QUAT_OPS_H_
+#define _GMTL_QUAT_OPS_H_
+
+#include <gmtl/Math.h>
+#include <gmtl/Quat.h>
+
+namespace gmtl
+{
+/** @ingroup Ops Quat 
+ * @name Quat Operations
+ * @{
+ */
+       
+   /** product of two quaternions (quaternion product)
+    *  multiplication of quats is much like multiplication of typical complex numbers.
+    *  @post q1q2 = (s1 + v1)(s2 + v2)
+    *  @post result = q1 * q2 (where q2 would be applied first to any xformed geometry)
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& mult( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      // Here is the easy to understand equation: (grassman product)
+      // scalar_component = q1.s * q2.s - dot(q1.v, q2.v)
+      // vector_component = q2.v * q1.s + q1.v * q2.s + cross(q1.v, q2.v)
+
+      // Here is another version (euclidean product, just FYI)...
+      // scalar_component = q1.s * q2.s + dot(q1.v, q2.v)
+      // vector_component = q2.v * q1.s - q1.v * q2.s - cross(q1.v, q2.v)
+
+      // Here it is, using vector algebra (grassman product)
+      /*
+      const float& w1( q1[Welt] ), w2( q2[Welt] );
+      Vec3 v1( q1[Xelt], q1[Yelt], q1[Zelt] ), v2( q2[Xelt], q2[Yelt], q2[Zelt] );
+
+      float w = w1 * w2 - v1.dot( v2 );
+      Vec3 v = (w1 * v2) + (w2 * v1) + v1.cross( v2 );
+
+      vec[Welt] = w;
+      vec[Xelt] = v[0];
+      vec[Yelt] = v[1];
+      vec[Zelt] = v[2];
+      */
+
+      // Here is the same, only expanded... (grassman product)
+      Quat<DATA_TYPE> temporary; // avoid aliasing problems...
+      temporary[Xelt] = q1[Welt]*q2[Xelt] + q1[Xelt]*q2[Welt] + q1[Yelt]*q2[Zelt] - q1[Zelt]*q2[Yelt];
+      temporary[Yelt] = q1[Welt]*q2[Yelt] + q1[Yelt]*q2[Welt] + q1[Zelt]*q2[Xelt] - q1[Xelt]*q2[Zelt];
+      temporary[Zelt] = q1[Welt]*q2[Zelt] + q1[Zelt]*q2[Welt] + q1[Xelt]*q2[Yelt] - q1[Yelt]*q2[Xelt];
+      temporary[Welt] = q1[Welt]*q2[Welt] - q1[Xelt]*q2[Xelt] - q1[Yelt]*q2[Yelt] - q1[Zelt]*q2[Zelt];
+
+      // use a temporary, in case q1 or q2 is the same as self.
+      result[Xelt] = temporary[Xelt];
+      result[Yelt] = temporary[Yelt];
+      result[Zelt] = temporary[Zelt];
+      result[Welt] = temporary[Welt];
+
+      // don't normalize, because it might not be rotation arithmetic we're doing
+      // (only rotation quats have unit length)
+      return result;
+   }
+
+   /** product of two quaternions (quaternion product)
+    *  Does quaternion multiplication.
+    *  @post temp' = q1 * q2 (where q2 would be applied first to any xformed geometry)
+    *  @see Quat
+    *  @todo metaprogramming on quat operator*()
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator*( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      // (grassman product - see mult() for discussion)
+      // don't normalize, because it might not be rotation arithmetic we're doing
+      // (only rotation quats have unit length)
+      return Quat<DATA_TYPE>( q1[Welt]*q2[Xelt] + q1[Xelt]*q2[Welt] + q1[Yelt]*q2[Zelt] - q1[Zelt]*q2[Yelt],
+                              q1[Welt]*q2[Yelt] + q1[Yelt]*q2[Welt] + q1[Zelt]*q2[Xelt] - q1[Xelt]*q2[Zelt],
+                              q1[Welt]*q2[Zelt] + q1[Zelt]*q2[Welt] + q1[Xelt]*q2[Yelt] - q1[Yelt]*q2[Xelt],
+                              q1[Welt]*q2[Welt] - q1[Xelt]*q2[Xelt] - q1[Yelt]*q2[Yelt] - q1[Zelt]*q2[Zelt] );
+   }
+
+   /** quaternion postmult
+    * @post result' = result * q2 (where q2 is applied first to any xformed geometry)
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator*=( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q2 )
+   {
+      return mult( result, result, q2 );
+   }
+
+   /** Vector negation - negate each element in the quaternion vector.
+    * the negative of a rotation quaternion is geometrically equivelent
+    * to the original. there exist 2 quats for every possible rotation.
+    * @return returns the negation of the given quat.
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& negate( Quat<DATA_TYPE>& result )
+   {
+      result[0] = -result[0];
+      result[1] = -result[1];
+      result[2] = -result[2];
+      result[3] = -result[3];
+      return result;
+   }
+
+   /** Vector negation - (operator-) return a temporary that is the negative of the given quat.
+    * the negative of a rotation quaternion is geometrically equivelent
+    * to the original. there exist 2 quats for every possible rotation.
+    * @return returns the negation of the given quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator-( const Quat<DATA_TYPE>& quat )
+   {
+      return Quat<DATA_TYPE>( -quat[0], -quat[1], -quat[2], -quat[3] );
+   }
+
+   /** vector scalar multiplication
+    * @post result' = [qx*s, qy*s, qz*s, qw*s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& mult( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      result[0] = q[0] * s;
+      result[1] = q[1] * s;
+      result[2] = q[2] * s;
+      result[3] = q[3] * s;
+      return result;
+   }
+
+   /** vector scalar multiplication
+    * @post result' = [qx*s, qy*s, qz*s, qw*s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator*( const Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      Quat<DATA_TYPE> temporary;
+      return mult( temporary, q, s );
+   }
+
+   /** vector scalar multiplication
+    * @post result' = [resultx*s, resulty*s, resultz*s, resultw*s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator*=( Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      return mult( q, q, s );
+   }
+
+   /** quotient of two quaternions
+    * @post result = q1 * (1/q2)  (where 1/q2 is applied first to any xform'd geometry)
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& div( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q1, Quat<DATA_TYPE> q2 )
+   {
+      // multiply q1 by the multiplicative inverse of the quaternion
+      return mult( result, q1, invert( q2 ) );
+   }
+
+   /** quotient of two quaternions
+    * @post result = q1 * (1/q2) (where 1/q2 is applied first to any xform'd geometry)
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator/( const Quat<DATA_TYPE>& q1, Quat<DATA_TYPE> q2 )
+   {
+      return q1 * invert( q2 );
+   }
+
+   /** quotient of two quaternions
+    * @post result = result * (1/q2)  (where 1/q2 is applied first to any xform'd geometry)
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator/=( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q2 )
+   {
+      return div( result, result, q2 );
+   }
+
+   /** quaternion vector scale
+    * @post result = q / s
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& div( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      result[0] = q[0] / s;
+      result[1] = q[1] / s;
+      result[2] = q[2] / s;
+      result[3] = q[3] / s;
+      return result;
+   }
+
+   /** vector scalar division
+    * @post result' = [qx/s, qy/s, qz/s, qw/s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator/( const Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      Quat<DATA_TYPE> temporary;
+      return div( temporary, q, s );
+   }
+
+   /** vector scalar division
+    * @post result' = [resultx/s, resulty/s, resultz/s, resultw/s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator/=( const Quat<DATA_TYPE>& q, DATA_TYPE s )
+   {
+      return div( q, q, s );
+   }
+
+   /** vector addition
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& add( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      result[0] = q1[0] + q2[0];
+      result[1] = q1[1] + q2[1];
+      result[2] = q1[2] + q2[2];
+      result[3] = q1[3] + q2[3];
+      return result;
+   }
+
+   /** vector addition
+    * @post result' = [qx+s, qy+s, qz+s, qw+s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator+( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      Quat<DATA_TYPE> temporary;
+      return add( temporary, q1, q2 );
+   }
+
+   /** vector addition
+    * @post result' = [resultx+s, resulty+s, resultz+s, resultw+s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator+=( Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      return add( q1, q1, q2 );
+   }
+
+   /** vector subtraction
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& sub( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      result[0] = q1[0] - q2[0];
+      result[1] = q1[1] - q2[1];
+      result[2] = q1[2] - q2[2];
+      result[3] = q1[3] - q2[3];
+      return result;
+   }
+
+   /** vector subtraction
+    * @post result' = [qx-s, qy-s, qz-s, qw-s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE> operator-( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      Quat<DATA_TYPE> temporary;
+      return sub( temporary, q1, q2 );
+   }
+
+   /** vector subtraction
+    * @post result' = [resultx-s, resulty-s, resultz-s, resultw-s]
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& operator-=( Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      return sub( q1, q1, q2 );
+   }
+
+   /** vector dot product between two quaternions.
+    *  get the lengthSquared between two quat vectors...
+    *  @post N(q) = x1*x2 + y1*y2 + z1*z2 + w1*w2
+    *  @return dot product of q1 and q2
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   DATA_TYPE dot( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      return DATA_TYPE( (q1[0] * q2[0]) +
+                        (q1[1] * q2[1]) +
+                        (q1[2] * q2[2]) +
+                        (q1[3] * q2[3])  );
+   }
+
+   /** quaternion "norm" (also known as vector length squared)
+    *  using this can be faster than using length for some operations...
+    *  @post returns the vector length squared
+    *  @post N(q) = x^2 + y^2 + z^2 + w^2
+    *  @post result = x*x + y*y + z*z + w*w
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   DATA_TYPE lengthSquared( const Quat<DATA_TYPE>& q )
+   {
+      return dot( q, q );
+   }
+
+   /** quaternion "absolute" (also known as vector length or magnitude)
+    *  using this can be faster than using length for some operations...
+    *  @post returns the magnitude of the 4D vector.
+    *  @post result = sqrt( lengthSquared( q ) )
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   DATA_TYPE length( const Quat<DATA_TYPE>& q )
+   {
+      return Math::sqrt( lengthSquared( q ) );
+   }
+
+   /** set self to the normalized quaternion of self.
+    *  @pre magnitude should be > 0, otherwise no calculation is done.
+    *  @post result' = normalize( result ), where normalize makes length( result ) == 1
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& normalize( Quat<DATA_TYPE>& result )
+   {
+      DATA_TYPE l = length( result );
+
+      // return if no magnitude (already as normalized as possible)
+      if (l < (DATA_TYPE)0.0001)
+         return result;
+
+      DATA_TYPE l_inv = ((DATA_TYPE)1.0) / l;
+      result[Xelt] *= l_inv;
+      result[Yelt] *= l_inv;
+      result[Zelt] *= l_inv;
+      result[Welt] *= l_inv;
+
+      return result;
+   }
+
+   /**
+    * Determines if the given quaternion is normalized within the given tolerance. The
+    * quaternion is normalized if its lengthSquared is 1.
+    *
+    * @param q1      the quaternion to test
+    * @param eps     the epsilon tolerance
+    *
+    * @return  true if the quaternion is normalized, false otherwise
+    */
+   template< typename DATA_TYPE >
+   bool isNormalized( const Quat<DATA_TYPE>& q1, const DATA_TYPE eps = 0.0001f )
+   {
+      return Math::isEqual( lengthSquared( q1 ), DATA_TYPE(1), eps );
+   }
+
+   /** quaternion complex conjugate.
+    *  @post set result to the complex conjugate of result.
+    *  @post q* = [s,-v]
+    *  @post result'[x,y,z,w] == result[-x,-y,-z,w]
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& conj( Quat<DATA_TYPE>& result )
+   {
+      result[Xelt] = -result[Xelt];
+      result[Yelt] = -result[Yelt];
+      result[Zelt] = -result[Zelt];
+      return result;
+   }
+
+   /** quaternion multiplicative inverse.
+    *  @post self becomes the multiplicative inverse of self
+    *  @post 1/q = q* / N(q)
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& invert( Quat<DATA_TYPE>& result )
+   {
+      // from game programming gems p198
+      // do result = conj( q ) / norm( q )
+      conj( result );
+
+      // return if norm() is near 0 (divide by 0 would result in NaN)
+      DATA_TYPE l = lengthSquared( result );
+      if (l < (DATA_TYPE)0.0001)
+         return result;
+
+      DATA_TYPE l_inv = ((DATA_TYPE)1.0) / l;
+      result[Xelt] *= l_inv;
+      result[Yelt] *= l_inv;
+      result[Zelt] *= l_inv;
+      result[Welt] *= l_inv;
+      return result;
+   }
+
+   /** complex exponentiation.
+    *  @pre safe to pass self as argument
+    *  @post sets self to the exponentiation of quat
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& exp( Quat<DATA_TYPE>& result )
+   {
+      DATA_TYPE len1, len2;
+
+      len1 = Math::sqrt( result[Xelt] * result[Xelt] +
+                         result[Yelt] * result[Yelt] +
+                         result[Zelt] * result[Zelt] );
+      if (len1 > (DATA_TYPE)0.0)
+         len2 = Math::sin( len1 ) / len1;
+      else
+         len2 = (DATA_TYPE)1.0;
+
+      result[Xelt] = result[Xelt] * len2;
+      result[Yelt] = result[Yelt] * len2;
+      result[Zelt] = result[Zelt] * len2;
+      result[Welt] = Math::cos( len1 );
+
+      return result;
+   }
+
+   /** complex logarithm
+    *  @post sets self to the log of quat
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& log( Quat<DATA_TYPE>& result )
+   {
+      DATA_TYPE length;
+
+      length = Math::sqrt( result[Xelt] * result[Xelt] +
+                           result[Yelt] * result[Yelt] +
+                           result[Zelt] * result[Zelt] );
+
+      // avoid divide by 0
+      if (Math::isEqual( result[Welt], (DATA_TYPE)0.0, (DATA_TYPE)0.00001 ) == false)
+         length = Math::aTan( length / result[Welt] );
+      else
+         length = Math::PI_OVER_2;
+
+      result[Welt] = (DATA_TYPE)0.0;
+      result[Xelt] = result[Xelt] * length;
+      result[Yelt] = result[Yelt] * length;
+      result[Zelt] = result[Zelt] * length;
+      return result;
+   }
+   
+   /** WARNING: not implemented (do not use) */
+   template <typename DATA_TYPE>
+   void squad( Quat<DATA_TYPE>& result, DATA_TYPE t, const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2, const Quat<DATA_TYPE>& a, const Quat<DATA_TYPE>& b )
+   {
+      gmtlASSERT( false );
+   }
+
+   /** WARNING: not implemented (do not use) */
+   template <typename DATA_TYPE>
+   void meanTangent( Quat<DATA_TYPE>& result, const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2, const Quat<DATA_TYPE>& q3 )
+   {
+       gmtlASSERT( false );
+   }
+
+
+   
+/** @} */
+   
+/** @ingroup Interp Quat 
+ * @name Quaternion Interpolation
+ * @{
+ */
+
+
+   /** spherical linear interpolation between two rotation quaternions.
+    *  t is a value between 0 and 1 that interpolates between from and to.
+    * @pre no aliasing problems to worry about ("result" can be "from" or "to" param).
+    * @param adjustSign - If true, then slerp will operate by adjusting the sign of the slerp to take shortest path
+    *
+    * References:
+    * <ul>
+    * <li> From Adv Anim and Rendering Tech. Pg 364
+    * </ul>
+    * @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& slerp( Quat<DATA_TYPE>& result, const DATA_TYPE t, const Quat<DATA_TYPE>& from, const Quat<DATA_TYPE>& to, bool adjustSign=true)
+   {
+      const Quat<DATA_TYPE>& p = from; // just an alias to match q
+
+      // calc cosine theta
+      DATA_TYPE cosom = dot( from, to );
+
+      // adjust signs (if necessary)
+      Quat<DATA_TYPE> q;
+      if (adjustSign && (cosom < (DATA_TYPE)0.0))
+      {
+         cosom = -cosom;
+         q[0] = -to[0];   // Reverse all signs
+         q[1] = -to[1];
+         q[2] = -to[2];
+         q[3] = -to[3];
+      }
+      else
+      {
+         q = to;
+      }
+
+      // Calculate coefficients
+      DATA_TYPE sclp, sclq;
+      if (((DATA_TYPE)1.0 - cosom) > (DATA_TYPE)0.0001) // 0.0001 -> some epsillon
+      {
+         // Standard case (slerp)
+         DATA_TYPE omega, sinom;
+         omega = gmtl::Math::aCos( cosom ); // extract theta from dot product's cos theta
+         sinom = gmtl::Math::sin( omega );
+         sclp  = gmtl::Math::sin( ((DATA_TYPE)1.0 - t) * omega ) / sinom;
+         sclq  = gmtl::Math::sin( t * omega ) / sinom;
+      }
+      else
+      {
+         // Very close, do linear interp (because it's faster)
+         sclp = (DATA_TYPE)1.0 - t;
+         sclq = t;
+      }
+
+      result[Xelt] = sclp * p[Xelt] + sclq * q[Xelt];
+      result[Yelt] = sclp * p[Yelt] + sclq * q[Yelt];
+      result[Zelt] = sclp * p[Zelt] + sclq * q[Zelt];
+      result[Welt] = sclp * p[Welt] + sclq * q[Welt];
+      return result;
+   }
+
+   /** linear interpolation between two quaternions.
+    *  t is a value between 0 and 1 that interpolates between from and to.
+    * @pre no aliasing problems to worry about ("result" can be "from" or "to" param).
+    * References:
+    * <ul>
+    * <li> From Adv Anim and Rendering Tech. Pg 364
+    * </ul>
+    *  @see Quat
+    */
+   template <typename DATA_TYPE>
+   Quat<DATA_TYPE>& lerp( Quat<DATA_TYPE>& result, const DATA_TYPE t, const Quat<DATA_TYPE>& from, const Quat<DATA_TYPE>& to)
+   {
+      // just an alias to match q
+      const Quat<DATA_TYPE>& p = from;
+
+      // calc cosine theta
+      DATA_TYPE cosom = dot( from, to );
+
+      // adjust signs (if necessary)
+      Quat<DATA_TYPE> q;
+      if (cosom < (DATA_TYPE)0.0)
+      {
+         q[0] = -to[0];   // Reverse all signs
+         q[1] = -to[1];
+         q[2] = -to[2];
+         q[3] = -to[3];
+      }
+      else
+      {
+         q = to;
+      }
+
+      // do linear interp
+      DATA_TYPE sclp, sclq;
+      sclp = (DATA_TYPE)1.0 - t;
+      sclq = t;
+
+      result[Xelt] = sclp * p[Xelt] + sclq * q[Xelt];
+      result[Yelt] = sclp * p[Yelt] + sclq * q[Yelt];
+      result[Zelt] = sclp * p[Zelt] + sclq * q[Zelt];
+      result[Welt] = sclp * p[Welt] + sclq * q[Welt];
+      return result;
+   }
+
+/** @} */
+
+/** @ingroup Compare Quat 
+ *  @name Quat Comparisons
+ * @{
+ */
+
+   /** Compare two quaternions for equality.
+    * @see isEqual( Quat, Quat )
+    */
+   template <typename DATA_TYPE>
+   inline bool operator==( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      return bool( q1[0] == q2[0] &&
+                   q1[1] == q2[1] &&
+                   q1[2] == q2[2] &&
+                   q1[3] == q2[3]  );
+   }
+
+   /** Compare two quaternions for not-equality.
+    * @see isEqual( Quat, Quat )
+    */
+   template <typename DATA_TYPE>
+   inline bool operator!=( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2 )
+   {
+      return !operator==( q1, q2 );
+   }
+
+   /** Compare two quaternions for equality with tolerance.
+    */
+   template <typename DATA_TYPE>
+   bool isEqual( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2, DATA_TYPE tol = 0.0 )
+   {
+      return bool( Math::isEqual( q1[0], q2[0], tol ) &&
+                   Math::isEqual( q1[1], q2[1], tol ) &&
+                   Math::isEqual( q1[2], q2[2], tol ) &&
+                   Math::isEqual( q1[3], q2[3], tol )    );
+   }
+
+   /** Compare two quaternions for geometric equivelence (with tolerance).
+    * there exist 2 quats for every possible rotation: the original,
+    * and its negative.  the negative of a rotation quaternion is geometrically
+    * equivelent to the original.
+    */
+   template <typename DATA_TYPE>
+   bool isEquiv( const Quat<DATA_TYPE>& q1, const Quat<DATA_TYPE>& q2, DATA_TYPE tol = 0.0 )
+   {
+      return bool( isEqual( q1, q2, tol ) || isEqual( q1, -q2, tol ) );
+   }
+   
+   /** @} */
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Ray.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Ray.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Ray.h	(revision 4)
@@ -0,0 +1,146 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Ray.h,v
+ * Date modified: 2003/02/23 07:16:49
+ * Version:       1.2
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_RAY_H_
+#define _GMTL_RAY_H_
+
+#include <gmtl/Point.h>
+#include <gmtl/Vec.h>
+#include <gmtl/VecOps.h>
+
+namespace gmtl {
+
+/**
+ * Describes a ray. This is represented by a point origin O and a
+ * normalized vector direction. Any point on the ray can be described as
+ *
+ * P(s) = O + Vs
+ *
+ * where 0 <= s <= 1
+ *
+ * @param DATA_TYPE     the internal type used for the point and vector
+ */
+template< class DATA_TYPE >
+class Ray
+{
+public:
+   /**
+    * Constructs a ray at the origin with a zero vector.
+    */
+   Ray()
+   {}
+
+   /**
+    * Constructs a ray with the given origin and vector.
+    *
+    * @param origin     the point at which the ray starts
+    * @param dir        the vector describing the direction and length of the
+    *                   ray starting at origin
+    */
+   Ray( const Point<DATA_TYPE, 3>& origin, const Vec<DATA_TYPE, 3>& dir )
+      : mOrigin( origin ), mDir( dir )
+   {}
+
+   
+
+   /**
+    * Constructs an exact duplicate of the given ray.
+    *
+    * @param lineseg    the ray to copy
+    */
+   Ray( const Ray& lineseg )
+   {
+      mOrigin = lineseg.mOrigin;
+      mDir = lineseg.mDir;
+   }
+
+   /**
+    * Gets the origin of the ray.
+    *
+    * @return  the point at the beginning of the line
+    */
+   const Point<DATA_TYPE, 3>& getOrigin() const
+   {
+      return mOrigin;
+   }
+
+   /**
+    * Sets the origin point for this ray.
+    *
+    * @param origin     the point at which the ray starts
+    */
+   void setOrigin( const Point<DATA_TYPE, 3>& origin )
+   {
+      mOrigin = origin;
+   }
+
+   /**
+    * Gets the vector describing the direction and length of the ray.
+    *
+    * @return  the ray's vector
+    */
+   const Vec<DATA_TYPE, 3>& getDir() const
+   {
+      return mDir;
+   }
+
+   /**
+    * Sets the vector describing the direction and length of the ray.
+    *
+    * @param dir     the ray's vector
+    */
+   void setDir( const Vec<DATA_TYPE, 3>& dir )
+   {
+      mDir = dir;
+   }
+
+public:
+   /**
+    * The origin of the ray.
+    */
+   Point<DATA_TYPE, 3> mOrigin;
+
+   /**
+    * The vector along which the ray lies.
+    */
+   Vec<DATA_TYPE, 3> mDir;
+};
+
+
+// --- helper types --- //
+typedef Ray<float>  Rayf;
+typedef Ray<double> Rayd;
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/RayOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/RayOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/RayOps.h	(revision 4)
@@ -0,0 +1,95 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          RayOps.h,v
+ * Date modified: 2003/05/10 21:18:01
+ * Version:       1.1
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_RAYOPS_H_
+#define _GMTL_RAYOPS_H_
+
+#include <gmtl/Ray.h>
+
+namespace gmtl {
+
+//--- Ray Comparitor ---//
+/**
+ * Compare two line segments to see if they are EXACTLY the same.
+ *
+ * @param ls1     the first Ray to compare
+ * @param ls2     the second Ray to compare
+ *
+ * @return  true if they are equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator==( const Ray<DATA_TYPE>& ls1, const Ray<DATA_TYPE>& ls2 )
+{
+   return ( (ls1.mOrigin == ls2.mOrigin) && (ls1.mDir == ls2.mDir) );
+}
+
+/**
+ * Compare two line segments to see if they are not EXACTLY the same.
+ *
+ * @param ls1     the first Ray to compare
+ * @param ls2     the second Ray to compare
+ *
+ * @return  true if they are not equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator!=( const Ray<DATA_TYPE>& ls1,
+                        const Ray<DATA_TYPE>& ls2 )
+{
+   return ( ! (ls1 == ls2) );
+}
+
+/**
+ * Compare two line segments to see if the are the same within the given
+ * tolerance.
+ *
+ * @param ls1     the first Ray to compare
+ * @param ls2     the second Ray to compare
+ * @param eps     the tolerance value to use
+ *
+ * @pre eps must be >= 0
+ *
+ * @return  true if they are equal within the tolerance, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool isEqual( const Ray<DATA_TYPE>& ls1,
+                     const Ray<DATA_TYPE>& ls2,
+                     const DATA_TYPE& eps )
+{
+   gmtlASSERT( eps >= 0 );
+   return ( (isEqual(ls1.mOrigin, ls2.mOrigin, eps)) &&
+            (isEqual(ls1.mDir, ls2.mDir, eps)) );
+}
+
+} // namespace gmtl
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Sphere.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Sphere.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Sphere.h	(revision 4)
@@ -0,0 +1,140 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Sphere.h,v
+ * Date modified: 2002/05/20 22:39:22
+ * Version:       1.5
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_SPHERE_H_
+#define _GMTL_SPHERE_H_
+
+#include <gmtl/Point.h>
+
+namespace gmtl
+{
+
+/**
+ * Describes a sphere in 3D space by its center point and its radius.
+ *
+ * @param DATA_TYPE     the internal type used for the point and radius
+ * @ingroup Types
+ */
+template<class DATA_TYPE>
+class Sphere
+{
+public:
+   typedef DATA_TYPE DataType;
+
+public:
+   /**
+    * Constructs a sphere centered at the origin with a radius of 0.
+    */
+   Sphere()
+      : mRadius( 0 )
+   {}
+
+   /**
+    * Constructs a sphere with the given center and radius.
+    *
+    * @param center     the point at which to center the sphere
+    * @param radius     the radius of the sphere
+    */
+   Sphere( const Point<DATA_TYPE, 3>& center, const DATA_TYPE& radius )
+      : mCenter( center ), mRadius( radius )
+   {}
+
+   /**
+    * Constructs a duplicate of the given sphere.
+    *
+    * @param sphere     the sphere to make a copy of
+    */
+   Sphere( const Sphere<DATA_TYPE>& sphere )
+      : mCenter( sphere.mCenter ), mRadius( sphere.mRadius )
+   {}
+
+   /**
+    * Gets the center of the sphere.
+    *
+    * @return  the center point of the sphere
+    */
+   const Point<DATA_TYPE, 3>& getCenter() const
+   {
+      return mCenter;
+   }
+
+   /**
+    * Gets the radius of the sphere.
+    *
+    * @return  the radius of the sphere
+    */
+   const DATA_TYPE& getRadius() const
+   {
+      return mRadius;
+   }
+
+   /**
+    * Sets the center point of the sphere.
+    *
+    * @param center     the new point at which to center the sphere
+    */
+   void setCenter( const Point<DATA_TYPE, 3>& center )
+   {
+      mCenter = center;
+   }
+
+   /**
+    * Sets the radius of the sphere.
+    *
+    * @param radius     the new radius of the sphere
+    */
+   void setRadius( const DATA_TYPE& radius )
+   {
+      mRadius = radius;
+   }
+
+public:
+   /**
+    * The center of the sphere.
+    */
+   Point<DATA_TYPE, 3> mCenter;
+
+   /**
+    * The radius of the sphere.
+    */
+   DATA_TYPE mRadius;
+};
+
+// --- helper types --- //
+typedef Sphere<float>   Spheref;
+typedef Sphere<double>  Sphered;
+
+};
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/SphereOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/SphereOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/SphereOps.h	(revision 4)
@@ -0,0 +1,101 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          SphereOps.h,v
+ * Date modified: 2003/08/30 17:13:13
+ * Version:       1.7
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_SPHEREOPS_H_
+#define _GMTL_SPHEREOPS_H_
+
+#include <gmtl/Sphere.h>
+#include <gmtl/VecOps.h>
+#include <gmtl/Math.h>
+
+namespace gmtl
+{
+
+/** @ingroup Compare Sphere 
+ * @name Sphere Comparitors
+ * @{
+ */
+
+/**
+ * Compare two spheres to see if they are EXACTLY the same. 
+ *
+ * @param s1      the first sphere to compare
+ * @param s2      the second sphere to compare
+ *
+ * @return  true if they are equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator==( const Sphere<DATA_TYPE>& s1, const Sphere<DATA_TYPE>& s2 )
+{
+   return ( (s1.mCenter == s2.mCenter) && (s1.mRadius == s2.mRadius) );
+}
+
+/**
+ * Compare two spheres to see if they are not EXACTLY the same. 
+ *
+ * @param s1      the first sphere to compare
+ * @param s2      the second sphere to compare
+ *
+ * @return  true if they are not equal, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool operator!=( const Sphere<DATA_TYPE>& s1, const Sphere<DATA_TYPE>& s2 )
+{
+   return (! (s1 == s2));
+}
+
+/**
+ * Compare two spheres to see if they are the same within the given tolerance.
+ *
+ * @param s1      the first sphere to compare
+ * @param s2      the second sphere to compare
+ * @param eps     the tolerance value to use
+ *
+ * @pre eps must be >= 0
+ *
+ * @return  true if they are equal within a tolerance, false otherwise
+ */
+template< class DATA_TYPE >
+inline bool isEqual( const Sphere<DATA_TYPE>& s1, const Sphere<DATA_TYPE>& s2, const DATA_TYPE& eps )
+{
+   gmtlASSERT( eps >= 0 );
+   return ( (isEqual(s1.mCenter, s2.mCenter, eps)) &&
+            (Math::isEqual(s1.mRadius, s2.mRadius, eps)) );
+}
+/** @} */
+
+} // namespace gmtl
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Tri.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Tri.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Tri.h	(revision 4)
@@ -0,0 +1,275 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Tri.h,v
+ * Date modified: 2004/11/12 01:28:44
+ * Version:       1.13
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_TRI_H_
+#define _GMTL_TRI_H_
+
+#include <gmtl/Point.h>
+#include <gmtl/Vec.h>
+#include <gmtl/VecOps.h>
+ 
+namespace gmtl
+{
+/**
+ * This class defines a triangle as a set of 3 points order in CCW fashion.
+ *
+ * Triangle points are tri(s,t) = b+s*e0+t*e1 where 0 <= s <= 1,
+ * 0 <= t <= 1, and 0 <= s+t <= 1.
+ * @ingroup Types
+ */
+template< class DATA_TYPE >
+class  Tri
+{
+public:
+   /**
+    * Constructs a new triangle with all vertices at the origin.
+    */
+   Tri() {}
+
+   /**
+    * Constructs a new triangle with the given points. The points must be passed
+    * in in CCW order.
+    *
+    * @param p1   vertex0
+    * @param p2   vertex1
+    * @param p3   vertex2
+    *
+    * @pre p1, p2, p3 must be in CCW order
+    */
+   Tri( const Point<DATA_TYPE, 3>& p1, const Point<DATA_TYPE, 3>& p2,
+        const Point<DATA_TYPE, 3>& p3)
+   {
+      mVerts[0] = p1;
+      mVerts[1] = p2;
+      mVerts[2] = p3;
+   }
+
+   /**
+    * Constructs a duplicate of the given triangle.
+    *
+    * @param tri     the triangle to copy
+    */
+   Tri( const Tri<DATA_TYPE>& tri )
+   {
+      mVerts[0] = tri[0];
+      mVerts[1] = tri[1];
+      mVerts[2] = tri[2];
+   }
+
+   /**
+    * Gets the nth vertex in the triangle.
+    *
+    * @param idx     the index to the vertex in the triangle
+    * @pre 0 <= idx <= 2
+    *
+    * @return  the nth vertex as a point
+    */
+   //@{
+   Point<DATA_TYPE, 3>& operator[]( const unsigned idx )
+   {
+      gmtlASSERT( idx <= 2 );
+      return mVerts[idx];
+   }
+   const Point<DATA_TYPE, 3>& operator[]( const unsigned idx ) const
+   {
+      gmtlASSERT( idx <= 2 );
+      return mVerts[idx];
+   }
+   //@}
+
+   /**
+    * Gets the nth edge of the triangle where edge0 corresponds to the vector
+    * from vertex 0 to 1, edge1 corresponds to the vector from vertex 1 to 2 and
+    * edge2 corresponsds to the vector from vertex 2 to vertex 0.
+    *
+    * @param   idx     the ordered edge index
+    * @pre 0 <= idx <= 2
+    *
+    * @return  a vector from vertex idx to vertex (idx+1)mod size
+    */
+   Vec<DATA_TYPE, 3> edge( int idx ) const
+   {
+      gmtlASSERT( (0 <= idx) && (idx <= 2) );
+      int idx2 = ( idx == 2 ) ? 0 : idx + 1;
+      return (mVerts[idx2] - mVerts[idx]);
+   }
+
+   /** get edge vec from two verts 
+    *
+    * @param   idx,idy     the ordered vertex indicies
+    * @pre 0 <= id <= 2
+    *
+    * @return  a vector from vertex idx to vertex idy
+    */
+   Vec<DATA_TYPE, 3> edge( int idx, int idy ) const
+   {
+      gmtlASSERT( (0 <= idx) && (idx <= 2) );
+      gmtlASSERT( (0 <= idy) && (idy <= 2) );
+      return (mVerts[idy] - mVerts[idx]);
+   }
+
+ 
+
+   /**
+    * Set the triangle with the given points. The points must be passed
+    * in in CCW order.
+    *
+    * @param p1   vertex0
+    * @param p2   vertex1
+    * @param p3   vertex2
+    *
+    * @pre p1, p2, p3 must be in CCW order
+    */
+   void set( const Point<DATA_TYPE, 3>& p1, const Point<DATA_TYPE, 3>& p2,
+           const Point<DATA_TYPE, 3>& p3 )
+   {
+      mVerts[0] = p1;
+      mVerts[1] = p2;
+      mVerts[2] = p3;
+   }
+
+private:
+   /**
+    * The vertices of the triangle.
+    */
+   Point<DATA_TYPE, 3> mVerts[3];
+};
+
+// convenience typedefs
+typedef Tri<float> Trif;
+typedef Tri<double> Trid;
+typedef Tri<int> Trii;
+}
+
+/*
+// Finds the point on the seg nearest to pt.
+// on the perimeter of the triangle.
+// Returns the nearest point in nearPt
+inline
+void sgTri::findNearestEdgePt(const sgVec3& pt, sgVec3& nearPt) const
+{
+    //      find all the closest pts on the segs that make the tri
+    //      return the closest one
+
+    sgSeg   seg1;   seg1.makePts(_v1, _v2);
+    sgSeg   seg2;   seg2.makePts(_v2, _v3);
+    sgSeg   seg3;   seg3.makePts(_v3, _v1);
+
+    sgVec3  pt1;    seg1.findNearestPt(pt, pt1);
+    sgVec3  pt2;    seg2.findNearestPt(pt, pt2);
+    sgVec3  pt3;    seg3.findNearestPt(pt, pt3);
+
+    float dist1 = SG_SQUARE(pt1[0]-pt[0]) + SG_SQUARE(pt1[1]-pt[1]) + SG_SQUARE(pt1[2]-pt[2]);
+    float dist2 = SG_SQUARE(pt2[0]-pt[0]) + SG_SQUARE(pt2[1]-pt[1]) + SG_SQUARE(pt2[2]-pt[2]);
+    float dist3 = SG_SQUARE(pt3[0]-pt[0]) + SG_SQUARE(pt3[1]-pt[1]) + SG_SQUARE(pt3[2]-pt[2]);
+
+    if((dist1 < dist2) && (dist1 < dist3))      // dist1 is min
+        nearPt = pt1;
+    else if(dist2 < dist3)                      // dist2 is min
+        nearPt = pt2;
+    else
+        nearPt = pt3;                           // dist3 is min
+}
+
+
+
+	// Returns wether the pt is in the triangle
+inline
+int sgTri::ptIn(const sgVec3& pt) const
+{
+		// Graphic Gems I: Page 392
+	int i0, i1, i2;	    // Axis indices
+	float u0, u1, u2, v0, v1, v2, alpha, beta;
+	i0 = 0;
+	
+    sgVec3  triNormal = (_v2-_v1).cross((_v3-_v1));
+    //sgPlane triPlane;
+    //triPlane.makePts(_v1, _v2, _v3);
+
+	// Find max index
+    // NOTE: note the fabs.  I added because of bug in GG code with negative normals
+	for(int index=0;index<3;index++)
+	if (fabs(triNormal.vec[index]) > fabs(triNormal.vec[i0]))
+		i0 = index;
+	
+	if(i0 == 0)
+		{ i1 = 1; i2 = 2; }
+	else if (i0 == 1)
+		{ i1 = 2; i2 = 0; }
+	else
+		{ i1 =0; i2 = 1; }
+	
+	u0 = pt[i1] - _v1[i1];
+	v0 = pt[i2] - _v1[i2];
+	u1 = _v2[i1] - _v1[i1];
+	u2 = _v3[i1] - _v1[i1];
+	v1 = _v2[i2] - _v1[i2];
+	v2 = _v3[i2] - _v1[i2];
+	if(u1 == 0)
+	{
+		beta = (u0/u2);
+		if((beta >= 0) && (beta<= 1))
+			alpha = (v0 - (beta*v2))/v1;
+	}
+	else
+	{
+		beta = ((v0*u1) - (u0*v1))/((v2*u1) - (u2*v1));
+		if((beta >= 0) && (beta<= 1))
+			alpha = (u0 - (beta*u2))/u1;
+	}
+	
+	return ((alpha >= 0) && (beta >= 0) && ((alpha+beta) <= 1));
+}
+
+
+
+// Finds the point on the seg nearest to pt.
+// Returns the nearest point in nearPt
+void sgTri::findNearestPt(const sgVec3& pt, sgVec3& nearPt) const
+{
+        // find nearest pt on plaane.
+        //      if it is in the tri, return it.
+        // Otherwise return the pt closest on the edge of the tri
+
+    sgPlane triPlane;
+    triPlane.makePts(_v1, _v2, _v3);
+    triPlane.findNearestPt(pt, nearPt);
+
+    if(!ptIn(nearPt))
+        findNearestEdgePt(pt, nearPt);
+}
+*/
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/TriOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/TriOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/TriOps.h	(revision 4)
@@ -0,0 +1,139 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          TriOps.h,v
+ * Date modified: 2004/09/16 21:21:10
+ * Version:       1.9
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_TRIOPS_H_
+#define _GMTL_TRIOPS_H_
+
+#include <gmtl/Tri.h>
+#include <gmtl/Generate.h>
+#include <gmtl/VecOps.h>
+
+namespace gmtl
+{
+/** @ingroup Ops Tri
+ *  @name Triangle Operations
+ * @{
+ */
+
+/**
+ * Computes the point at the center of the given triangle.
+ *
+ * @param tri     the triangle to find the center of
+ *
+ * @return  the point at the center of the triangle
+ */
+template< class DATA_TYPE >
+Point<DATA_TYPE, 3> center( const Tri<DATA_TYPE>& tri )
+{
+   const float one_third = (1.0f/3.0f);
+   return (tri[0] + tri[1] + tri[2]) * DATA_TYPE(one_third);
+}
+
+/**
+ * Computes the normal for this triangle.
+ *
+ * @param tri     the triangle for which to compute the normal
+ *
+ * @return  the normal vector for tri
+ */
+template< class DATA_TYPE >
+Vec<DATA_TYPE, 3> normal( const Tri<DATA_TYPE>& tri )
+{
+   Vec<DATA_TYPE, 3> normal = makeCross( gmtl::Vec<DATA_TYPE,3>(tri[1] - tri[0]), gmtl::Vec<DATA_TYPE,3>(tri[2] - tri[0]) );
+   normalize( normal );
+   return normal;
+}
+/** @} */
+
+/** @ingroup Compare Tri
+ *  @name Triangle Comparitors
+ *  @{
+ */
+
+/**
+ * Compare two triangles to see if they are EXACTLY the same.
+ *
+ * @param tri1    the first triangle to compare
+ * @param tri2    the second triangle to compare
+ *
+ * @return  true if they are equal, false otherwise
+ */
+template< class DATA_TYPE >
+bool operator==( const Tri<DATA_TYPE>& tri1, const Tri<DATA_TYPE>& tri2 )
+{
+   return ( (tri1[0] == tri2[0]) &&
+            (tri1[1] == tri2[1]) &&
+            (tri1[2] == tri2[2]) );
+}
+
+/**
+ * Compare two triangle to see if they are not EXACTLY the same.
+ *
+ * @param tri1    the first triangle to compare
+ * @param tri2    the second triangle to compare
+ *
+ * @return  true if they are not equal, false otherwise
+ */
+template< class DATA_TYPE >
+bool operator!=( const Tri<DATA_TYPE>& tri1, const Tri<DATA_TYPE>& tri2 )
+{
+   return (! (tri1 == tri2));
+}
+
+/**
+ * Compare two triangles to see if they are the same within the given tolerance.
+ *
+ * @param tri1    the first triangle to compare
+ * @param tri2    the second triangle to compare
+ * @param eps     the tolerance value to use
+ *
+ * @pre  eps must be >= 0
+ *
+ * @return  true if they are equal within the tolerance, false otherwise
+ */
+template< class DATA_TYPE >
+bool isEqual( const Tri<DATA_TYPE>& tri1, const Tri<DATA_TYPE>& tri2,
+              const DATA_TYPE& eps )
+{
+   gmtlASSERT( eps >= 0 );
+   return ( isEqual(tri1[0], tri2[0], eps) &&
+            isEqual(tri1[1], tri2[1], eps) &&
+            isEqual(tri1[2], tri2[2], eps) );
+}
+/** @} */
+
+} // namespace gmtl
+
+#endif
+
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Util/Assert.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Util/Assert.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Util/Assert.h	(revision 4)
@@ -0,0 +1,47 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Assert.h,v
+ * Date modified: 2004/02/23 17:11:06
+ * Version:       1.2
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef GMTL_ASSERT_H
+#define GMTL_ASSERT_H
+
+// -- VERY simple assertion stuff -- //
+#ifdef _DEBUG
+#   include <assert.h>
+#   define gmtlASSERT(val) assert((val))
+#else
+#   define gmtlASSERT(val) ((void)0)
+#endif
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Util/Meta.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Util/Meta.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Util/Meta.h	(revision 4)
@@ -0,0 +1,137 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Meta.h,v
+ * Date modified: 2004/10/30 18:24:34
+ * Version:       1.3
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_METAPROGRAMMING_H
+#define _GMTL_METAPROGRAMMING_H
+
+#include <gmtl/Defines.h>
+
+/*** STRINGIZE and JOIN macros */
+/* Taken from boost (see boost.org) */
+
+//
+// Helper macro GMTL_STRINGIZE:
+// Converts the parameter X to a string after macro replacement
+// on X has been performed.
+//
+#define GMTL_STRINGIZE(X) GMTL_DO_STRINGIZE(X)
+#define GMTL_DO_STRINGIZE(X) #X
+
+//
+// Helper macro GMTL_JOIN:
+// The following piece of macro magic joins the two
+// arguments together, even when one of the arguments is
+// itself a macro (see 16.3.1 in C++ standard).  The key
+// is that macro expansion of macro arguments does not
+// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN.
+//
+#define GMTL_JOIN( X, Y ) GMTL_DO_JOIN( X, Y )
+#define GMTL_DO_JOIN( X, Y ) GMTL_DO_JOIN2(X,Y)
+#define GMTL_DO_JOIN2( X, Y ) X##Y
+
+
+/** Meta programming classes */
+namespace gmtl
+{
+   /** @ingroup Meta */
+   //@{
+
+   /** A lightweight identifier you can pass to overloaded functions
+    *  to typefy them.
+    *
+    *  Type2Type lets you transport the type information about T to functions
+    */
+   template <typename T>
+   struct Type2Type
+   {
+      typedef T OriginalType;
+   };
+
+   //@}
+
+   /** @ingroup HelperMeta */
+   //@{
+   template <class T> inline void ignore_unused_variable_warning(const T&) { }
+
+   //@}
+
+} // end namespace
+
+#ifndef GMTL_NO_METAPROG
+namespace gmtl
+{
+namespace meta
+{
+
+// ------ LOOP UnRolling ------------ //
+template<int ELT, typename T>
+struct AssignVecUnrolled
+{
+   static void func(T& lVec, const T& rVec)
+   {
+      AssignVecUnrolled<ELT-1,T>::func(lVec, rVec);
+      lVec[ELT] = rVec[ELT];
+   }
+};
+
+template<typename T>
+struct AssignVecUnrolled<0,T>
+{
+   static void func(T& lVec, const T& rVec)
+   { lVec[0] = rVec[0]; }
+};
+
+// Template programs for array assignment unrolled
+template<int ELT, typename T>
+struct AssignArrayUnrolled
+{
+   static void func(T* lVec, const T* rVec)
+   {
+      AssignArrayUnrolled<ELT-1,T>::func(lVec, rVec);
+      lVec[ELT] = rVec[ELT];
+   }
+};
+
+template<typename T>
+struct AssignArrayUnrolled<0,T>
+{
+   static void func(T* lVec, const T* rVec)
+   { lVec[0] = rVec[0]; }
+};
+
+}  // namespace meta
+}  // namespace gmtl
+#endif /* ! GMTL_NO_METAPROG */
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Util/StaticAssert.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Util/StaticAssert.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Util/StaticAssert.h	(revision 4)
@@ -0,0 +1,100 @@
+/** Static assertion macros 
+* Borrowed from boost and Loki.
+*/
+#ifndef GMTL_STATIC_ASSERT_HPP
+#define GMTL_STATIC_ASSERT_HPP
+
+namespace gmtl
+{
+   /**
+    * Define a structure that will contain our static assert; the name 
+    * CompileTimeError will hopefully be displayed and catch the eye of the
+    * programmer.
+    */
+   template <int> struct CompileTimeError;
+   template <> struct CompileTimeError<true> {};
+}
+/**
+ * GMTL_STATIC_ASSERT macro.
+ * This macro will evaluate a compile time integral or pointer expression;
+ * if the expression is zero, the macro will generate a message in the form
+ * of an undefined identifier.
+ *
+ * @param   expr     the expression to evaluate.
+ * @param   msg      the message to display if expr is zero; msg cannot
+ *                   contain spaces!
+ */
+#define GMTL_STATIC_ASSERT(expr, msg) \
+   { gmtl::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
+
+// -- OLD Static assert --- //
+// -- To be used if the new one causes problems -- //
+/*
+#include <gmtl/Defines.h>
+#include <gmtl/Util/Meta.h>
+
+#ifdef __BORLANDC__
+//
+// workaround for buggy integral-constant expression support:
+#define GMTL_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS
+#endif
+
+namespace gmtl
+{
+
+// HP aCC cannot deal with missing names for template value parameters
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+
+template <> struct STATIC_ASSERTION_FAILURE<true>{};
+
+// HP aCC cannot deal with missing names for template value parameters
+template<int x> struct static_assert_test{};
+
+}
+
+//
+// Implicit instantiation requires that all member declarations be
+// instantiated, but that the definitions are *not* instantiated.
+//
+// It's not particularly clear how this applies to enum's or typedefs;
+// both are described as declarations [7.1.3] and [7.2] in the standard,
+// however some compilers use "delayed evaluation" of one or more of
+// these when implicitly instantiating templates.  We use typedef declarations
+// by default, but try defining BOOST_USE_ENUM_STATIC_ASSERT if the enum
+// version gets better results from your compiler...
+//
+// Implementation:
+// Both of these versions rely on sizeof(incomplete_type) generating an error
+// message containing the name of the incomplete type.  We use
+// "STATIC_ASSERTION_FAILURE" as the type name here to generate
+// an eye catching error message.  The result of the sizeof expression is either
+// used as an enum initialiser, or as a template argument depending which version
+// is in use...
+// Note that the argument to the assert is explicitly cast to bool using old-
+// style casts: too many compilers currently have problems with static_cast
+// when used inside integral constant expressions.
+//
+#if !defined(GMTL_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS) && !defined(__MWERKS__)
+#ifndef GMTL_MSVC
+#define GMTL_STATIC_ASSERT( B ) \
+   typedef ::gmtl::static_assert_test<\
+      sizeof(::gmtl::STATIC_ASSERTION_FAILURE< (bool)( B ) >)>\
+         GMTL_JOIN(gmtl_static_assert_typedef_, __LINE__)
+#else
+// __LINE__ macro broken when -ZI is used see Q199057
+// fortunately MSVC ignores duplicate typedef's.
+#define GMTL_STATIC_ASSERT( B ) \
+   typedef ::gmtl::static_assert_test<\
+      sizeof(::gmtl::STATIC_ASSERTION_FAILURE< (bool)( B ) >)\
+      > gmtl_static_assert_typedef_
+#endif
+#else
+// alternative enum based implementation:
+#define GMTL_STATIC_ASSERT( B ) \
+   enum { GMTL_JOIN(gmtl_static_assert_enum_, __LINE__) \
+      = sizeof(::gmtl::STATIC_ASSERTION_FAILURE< (bool)( B ) >) }
+#endif
+
+*/
+
+#endif // GMTL_STATIC_ASSERT_HPP
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Vec.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Vec.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Vec.h	(revision 4)
@@ -0,0 +1,164 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Vec.h,v
+ * Date modified: 2004/11/12 01:34:49
+ * Version:       1.21
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VEC_H_
+#define _GMTL_VEC_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Config.h>
+#include <gmtl/VecBase.h>
+#include <gmtl/Util/StaticAssert.h>
+
+namespace gmtl
+{
+
+/**
+ * A representation of a vector with SIZE components using DATA_TYPE as the data
+ * type for each component.
+ *
+ * @param DATA_TYPE     the datatype to use for the components
+ * @param SIZE          the number of components this VecBase has
+ * @see Vec3f
+ * @see Vec4f
+ * @see Vec3d
+ * @see Vec4f
+ * @ingroup Types
+ */
+template<class DATA_TYPE, unsigned SIZE>
+#ifdef GMTL_NO_METAPROG
+class Vec : public VecBase<DATA_TYPE, SIZE>
+#else
+class Vec : public VecBase<DATA_TYPE, SIZE, meta::DefaultVecTag>
+#endif
+{
+public:
+   /// The datatype used for the components of this Vec.
+   typedef DATA_TYPE DataType;
+
+   /// The number of components this Vec has.
+   enum Params { Size = SIZE };
+
+   /// The superclass type.
+   typedef VecBase<DATA_TYPE, SIZE> BaseType;
+   typedef Vec<DATA_TYPE, SIZE> VecType;
+
+public:
+   /**
+    * Default constructor. All components are initialized to zero.
+    */
+   Vec()
+   {
+      for (unsigned i = 0; i < SIZE; ++i)
+         this->mData[i] = (DATA_TYPE)0;
+   }
+
+   /// @name Value constructors
+   //@{
+   /**
+    * Make an exact copy of the given Vec object.
+    * @pre  Vector should be the same size and type as the one copied
+    * @param rVec    the Vec object to copy
+    */
+   /*
+   Vec( const Vec<DATA_TYPE, SIZE>& rVec )
+      : BaseType( static_cast<BaseType>( rVec ) )
+   {;}
+   */
+
+#ifdef GMTL_NO_METAPROG
+   Vec( const VecBase<DATA_TYPE, SIZE>& rVec )
+      : BaseType( rVec )
+   {
+   }
+#else
+   template<typename REP2>
+   Vec( const VecBase<DATA_TYPE, SIZE, REP2>& rVec )
+      : BaseType( rVec )
+   {
+   }
+#endif
+
+   /**
+    * Creates a new Vec initialized to the given values.
+    */
+   Vec(const DATA_TYPE& val0,const DATA_TYPE& val1)
+   : BaseType(val0, val1)
+   {
+      GMTL_STATIC_ASSERT( SIZE == 2, Out_Of_Bounds_Element_Access_In_Vec );
+   }
+
+   Vec(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2)
+   : BaseType(val0, val1, val2)
+   {
+      GMTL_STATIC_ASSERT( SIZE == 3, Out_Of_Bounds_Element_Access_In_Vec );
+   }
+
+   Vec(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2,const DATA_TYPE& val3)
+   : BaseType(val0, val1, val2, val3)
+   {
+      GMTL_STATIC_ASSERT( SIZE == 4, Out_Of_Bounds_Element_Access_In_Vec );
+   }
+   //@}
+
+   /** Assign from different rep. */
+#ifdef GMTL_NO_METAPROG
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE>& rhs)
+   {
+      BaseType::operator=(rhs);
+      return *this;
+   }
+#else
+   template<typename REP2>
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE,REP2>& rhs)
+   {
+      BaseType::operator=(rhs);
+      return *this;
+   }
+#endif
+};
+
+// --- helper types --- //
+typedef Vec<int, 2> Vec2i;
+typedef Vec<float,2> Vec2f;
+typedef Vec<double,2> Vec2d;
+typedef Vec<int, 3> Vec3i;
+typedef Vec<float,3> Vec3f;
+typedef Vec<double,3> Vec3d;
+typedef Vec<int, 4> Vec4i;
+typedef Vec<float,4> Vec4f;
+typedef Vec<double,4> Vec4d;
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/VecBase.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/VecBase.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/VecBase.h	(revision 4)
@@ -0,0 +1,335 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          VecBase.h,v
+ * Date modified: 2005/06/06 03:44:49
+ * Version:       1.20
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VECBASE_H_
+#define _GMTL_VECBASE_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Util/Assert.h>
+#include <gmtl/Util/StaticAssert.h>
+#include <gmtl/Util/Meta.h>
+#include <gmtl/Config.h>
+#include <gmtl/Helpers.h>
+
+
+namespace gmtl
+{
+
+#ifndef GMTL_NO_METAPROG
+namespace meta
+{
+   struct DefaultVecTag
+   {};
+}
+#endif
+
+
+/**
+ * Base type for vector-like objects including Points and Vectors. It is
+ * templated on the component datatype as well as the number of components that
+ * make it up.
+ *
+ * @param DATA_TYPE  the datatype to use for the components
+ * @param SIZE       the number of components this VecB has
+ * @param REP        the representation to use for the vector.  (expression template or default)
+ */
+#ifndef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE, typename REP=meta::DefaultVecTag>
+class VecBase
+{
+protected:
+   const REP  expRep;      // The expression rep
+
+public:
+   /// The datatype used for the components of this VecB.
+   typedef DATA_TYPE DataType;
+
+   /// The number of components this VecB has.
+   enum Params { Size = SIZE };
+
+public:
+   VecBase()
+   {;}
+
+   VecBase(const REP& rep)
+      : expRep(rep)
+   {;}
+
+   /** Conversion operator to default vecbase type. */
+   /*
+   operator VecBase<DATA_TYPE,SIZE,meta::DefaultVecTag>()
+   {
+      return VecBase<DATA_TYPE,SIZE,meta::DefaultVecTag>(*this);
+   }
+   */
+
+   /** Return the value at given location. */
+   inline DATA_TYPE operator [](const unsigned i)
+   {
+      gmtlASSERT(i < SIZE);
+      return expRep[i];
+   }
+   inline const DATA_TYPE  operator [](const unsigned i) const
+   {
+      gmtlASSERT(i < SIZE);
+      return expRep[i];
+   }
+};
+#endif
+
+
+/**
+ * Specialized version of VecBase that is actually used for all user interaction
+ * with a traditional vector.
+ *
+ * @param DATA_TYPE  the datatype to use for the components
+ * @param SIZE       the number of components this VecBase has
+ */
+template<class DATA_TYPE, unsigned SIZE>
+#ifdef GMTL_NO_METAPROG
+class VecBase
+#else
+class VecBase<DATA_TYPE,SIZE,meta::DefaultVecTag>
+#endif
+{
+public:
+   /// The datatype used for the components of this VecBase.
+   typedef DATA_TYPE DataType;
+
+#ifdef GMTL_NO_METAPROG
+   typedef VecBase<DATA_TYPE, SIZE> VecType;
+#else
+   typedef VecBase<DATA_TYPE, SIZE, meta::DefaultVecTag> VecType;
+#endif
+
+   /// The number of components this VecBase has.
+   enum Params { Size = SIZE };
+
+public:
+   /**
+    * Default constructor.
+    * Does nothing, leaves data alone.
+    * This is for performance because this constructor is called by derived class constructors
+    * Even when they just want to set the data directly
+    */
+   VecBase()
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+   }
+
+   /**
+    * Makes an exact copy of the given VecBase object.
+    *
+    * @param rVec    the VecBase object to copy
+    */
+   VecBase(const VecBase<DATA_TYPE, SIZE>& rVec)
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+#ifdef GMTL_NO_METAPROG
+      for(unsigned i=0;i<SIZE;++i)
+         mData[i] = rVec.mData[i];
+#else
+      gmtl::meta::AssignVecUnrolled<SIZE-1, VecBase<DATA_TYPE,SIZE> >::func(*this, rVec);
+#endif
+   }
+
+#ifndef GMTL_NO_METAPROG
+   template<typename REP2>
+   VecBase(const VecBase<DATA_TYPE, SIZE, REP2>& rVec)
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+      for(unsigned i=0;i<SIZE;++i)
+      {  mData[i] = rVec[i]; }
+   }
+#endif
+
+   //@{
+   /**
+    * Creates a new VecBase initialized to the given values.
+    */
+   VecBase(const DATA_TYPE& val0,const DATA_TYPE& val1)
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+      GMTL_STATIC_ASSERT( SIZE == 2, Invalid_constructor_of_size_2_used);
+      mData[0] = val0; mData[1] = val1;
+   }
+   VecBase(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2)
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+      GMTL_STATIC_ASSERT( SIZE == 3, Invalid_constructor_of_size_3_used );
+      mData[0] = val0;  mData[1] = val1;  mData[2] = val2;
+   }
+   VecBase(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2,const DATA_TYPE& val3)
+   {
+#ifdef GMTL_COUNT_CONSTRUCT_CALLS
+      gmtl::helpers::VecCtrCounterInstance()->inc();
+#endif
+      // @todo need compile time assert
+      GMTL_STATIC_ASSERT( SIZE == 4, Invalid_constructor_of_size_4_used);
+      mData[0] = val0;  mData[1] = val1;  mData[2] = val2;  mData[3] = val3;
+   }
+   //@}
+
+   /**
+    * Sets the components in this VecBase using the given array.
+    *
+    * @param dataPtr    the array containing the values to copy
+    * @pre dataPtr has at least SIZE elements
+    */
+   inline void set(const DATA_TYPE* dataPtr)
+   {
+#ifdef GMTL_NO_METAPROG
+      for ( unsigned int i = 0; i < SIZE; ++i )
+      {
+         mData[i] = dataPtr[i];
+      }
+#else
+      gmtl::meta::AssignArrayUnrolled<SIZE-1, DATA_TYPE>::func(&(mData[0]),
+                                                               dataPtr);
+#endif
+   }
+
+   //@{
+   /**
+    * Sets the components in this VecBase to the given values.
+    */
+   inline void set(const DATA_TYPE& val0)
+   { mData[0] = val0; }
+
+   inline void set(const DATA_TYPE& val0,const DATA_TYPE& val1)
+   {
+      GMTL_STATIC_ASSERT( SIZE >= 2, Set_out_of_valid_range);
+      mData[0] = val0; mData[1] = val1;
+   }
+   inline void set(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2)
+   {
+      GMTL_STATIC_ASSERT( SIZE >= 3, Set_out_of_valid_range);
+      mData[0] = val0;  mData[1] = val1;  mData[2] = val2;
+   }
+   inline void set(const DATA_TYPE& val0,const DATA_TYPE& val1,const DATA_TYPE& val2,const DATA_TYPE& val3)
+   {
+      GMTL_STATIC_ASSERT( SIZE >= 4, Set_out_of_valid_range);
+      mData[0] = val0;  mData[1] = val1;  mData[2] = val2;  mData[3] = val3;
+   }
+   //@}
+
+   //@{
+   /**
+    * Gets the ith component in this VecBase.
+    *
+    * @param i    the zero-based index of the component to access.
+    * @pre i < SIZE
+    *
+    * @return  a reference to the ith component
+    */
+   inline DATA_TYPE& operator [](const unsigned i)
+   {
+      gmtlASSERT(i < SIZE);
+      return mData[i];
+   }
+   inline const DATA_TYPE&  operator [](const unsigned i) const
+   {
+      gmtlASSERT(i < SIZE);
+      return mData[i];
+   }
+   //@}
+
+   /** Assign from different rep. */
+#ifdef GMTL_NO_METAPROG
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE>& rhs)
+   {
+      for(unsigned i=0;i<SIZE;++i)
+      {
+         mData[i] = rhs[i];
+      }
+
+      return *this;
+   }
+#else
+   template<typename REP2>
+   inline VecType& operator=(const VecBase<DATA_TYPE,SIZE,REP2>& rhs)
+   {
+      for(unsigned i=0;i<SIZE;++i)
+      {
+         mData[i] = rhs[i];
+      }
+
+      //gmtl::meta::AssignVecUnrolled<SIZE-1, VecBase<DATA_TYPE,SIZE> >::func(*this, rVec);
+      return *this;
+   }
+#endif
+
+   /*
+    Assign from another of same type.
+   inline VecType& operator=(const VecType&  rhs)
+   {
+      for(unsigned i=0;i<SIZE;++i)
+      {
+         mData[i] = rhs[i];
+      }
+      return *this;
+   }
+*/
+
+   //@{
+   /**
+    * Gets the internal array of the components.
+    *
+    * @return  a pointer to the component array with length SIZE
+    */
+   DATA_TYPE* getData()
+   { return mData; }
+   const DATA_TYPE* getData() const
+   { return mData; }
+   //@}
+
+public:
+   /// The array of components.
+   DATA_TYPE mData[SIZE];
+};
+
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/VecExprMeta.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/VecExprMeta.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/VecExprMeta.h	(revision 4)
@@ -0,0 +1,213 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          VecExprMeta.h,v
+ * Date modified: 2004/11/11 21:34:33
+ * Version:       1.3
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VEC_EXPR_META_H
+#define _GMTL_VEC_EXPR_META_H
+
+#include <gmtl/Util/Meta.h>
+#include <gmtl/VecOpsMeta.h>
+#include <gmtl/VecBase.h>
+
+/** Expression template classes for vec operations
+ */
+namespace gmtl
+{
+namespace meta
+{
+/** @ingroup VecExprMeta */
+//@{
+
+
+// ------------ Expression templates primitives ----------- //
+// Expression templates for vectors
+//
+// NOTE: These could probably be optimized more in the future
+
+// Concepts:
+//
+// VectorExpression:
+//    types:
+//    interface:
+//       TYPE eval(unsigned i):  Returns evaluation of expression at elt i
+
+
+/** template to hold a scalar argument. */
+template <typename T>
+struct ScalarArg
+{
+   typedef T DataType;
+
+   const T mScalar;
+
+   inline ScalarArg(const T scalar) : mScalar(scalar) {}
+   inline T operator[](const unsigned) const
+   { return mScalar; }
+};
+
+template <typename T>
+inline ScalarArg<T> makeScalarArg(T val)
+{ return ScalarArg<T>(val); }
+
+// --- TRAITS --- //
+/** Traits class for expression template parameters.
+* NOTE: These types are VERY important to the performance of the code.
+*    They allow the compiler to optimize (ie. eliminate) much code.
+*/
+template<typename T>
+struct ExprTraits
+{
+   typedef const T ExprRef;     // Refer using a constant reference
+};
+
+template<typename T, unsigned SIZE>
+struct ExprTraits< VecBase<T, SIZE, ScalarArg<T> > >
+{
+   typedef const VecBase<T,SIZE,ScalarArg<T> > ExprRef;
+};
+
+template<typename T, unsigned SIZE>
+struct ExprTraits< VecBase<T, SIZE, DefaultVecTag> >
+{
+   typedef const VecBase<T,SIZE,DefaultVecTag>& ExprRef;
+};
+
+
+// -- Expressions -- //
+/** Binary vector expression.
+*
+* Stores the two vector expressions to process.
+*/
+template <typename EXP1_T, typename EXP2_T, typename OP>
+struct VecBinaryExpr
+{
+   typedef typename EXP1_T::DataType DataType;
+
+   typename ExprTraits<EXP1_T>::ExprRef Exp1;
+   typename ExprTraits<EXP2_T>::ExprRef Exp2;
+
+   inline VecBinaryExpr(const EXP1_T& e1, const EXP2_T& e2) : Exp1(e1), Exp2(e2) {;}
+   inline DataType operator[](const unsigned i) const
+   { return OP::eval(Exp1[i], Exp2[i]); }
+};
+
+/** Unary vector expression.
+* Holds the vector expression and unary operation to apply to it.
+*/
+template <typename EXP1_T, typename OP>
+struct VecUnaryExpr
+{
+   typedef typename EXP1_T::DataType DataType;
+
+   typename ExprTraits<EXP1_T>::ExprRef Exp1;
+
+   inline VecUnaryExpr(const EXP1_T& e1) : Exp1(e1) {;}
+   inline DataType operator[](const unsigned i) const
+   { return OP::eval(Exp1[i]); }
+};
+
+// --- Operations --- //
+/* Binary operations to add two vector expressions. */
+struct VecPlusBinary
+{
+   template <typename T>
+   static inline T eval(const T a1, const T a2)
+   { return a1+a2; }
+};
+
+/* Binary operations to subtract two vector expressions. */
+struct VecMinusBinary
+{
+   template <typename T>
+   static inline T eval(const T a1, const T a2)
+   { return a1-a2; }
+};
+
+struct VecMultBinary
+{
+   template<typename T>
+   static inline T eval(const T a1, const T a2)
+   { return a1 * a2; }
+};
+
+struct VecDivBinary
+{
+   template<typename T>
+   static inline T eval(const T a1, const T a2)
+   { return a1/a2; }
+};
+
+/** Negation of the values. */
+struct VecNegUnary
+{
+   template <typename T>
+   static inline T eval(const T a1)
+   { return -a1; }
+};
+
+
+/*
+template<typename T, unsigned SIZE, typename R1, typename R2>
+inline VecBase<T,SIZE, VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,R2>, VecPlusBinary> >
+sum(const VecBase<T,SIZE,R1>& v1, const VecBase<T,SIZE,R2>& v2)
+{
+   return VecBase<T,SIZE,
+               VecBinaryExpr<VecBase<T,SIZE,R1>,
+                             VecBase<T,SIZE,R2>,
+                             VecPlusBinary> >( VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                             VecBase<T,SIZE,R2>,
+                                                             VecPlusBinary>(v1,v2) );
+}
+
+
+template<typename T, unsigned SIZE, typename R1>
+inline VecBase<T,SIZE, VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,ScalarArg<T> >, VecPlusBinary> >
+sum(const VecBase<T,SIZE,R1>& v1, const T& arg)
+{
+   return VecBase<T,SIZE,
+               VecBinaryExpr<VecBase<T,SIZE,R1>,
+                             VecBase<T,SIZE,ScalarArg<T> >,
+                             VecPlusBinary> >( VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                             VecBase<T,SIZE,ScalarArg<T> >,
+                                                             VecPlusBinary>(v1,ScalarArg<T>(arg)) );
+}
+*/
+
+//@}
+
+
+} // namespace meta
+} // end namespace
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/VecOps.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/VecOps.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/VecOps.h	(revision 4)
@@ -0,0 +1,651 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          VecOps.h,v
+ * Date modified: 2005/12/03 20:54:25
+ * Version:       1.34
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VEC_OPS_H_
+#define _GMTL_VEC_OPS_H_
+
+#include <gmtl/Defines.h>
+#include <gmtl/Math.h>
+#include <gmtl/Vec.h>
+#ifndef GMTL_NO_METAPROG
+#include <gmtl/VecOpsMeta.h>
+#include <gmtl/VecExprMeta.h>
+#endif
+
+namespace gmtl
+{
+
+/** @ingroup Ops
+ * @name Vector/Point Operations
+ * @{
+ */
+
+// --- Basic VEC types operations -- //
+
+/**
+ * Negates v1.  The result = -v1.
+ *
+ * @param v1   the vector.
+ *
+ * @return  the result of negating v1.
+ */
+#ifdef GMTL_NO_METAPROG
+template<typename DATA_TYPE, unsigned SIZE>
+Vec<DATA_TYPE, SIZE> operator- (const VecBase<DATA_TYPE, SIZE>& v1)
+{
+   Vec<DATA_TYPE, SIZE> ret_val;
+   for ( unsigned i=0; i < SIZE; ++i )
+   {
+      ret_val[i] = -v1[i];
+   }
+   return ret_val;
+}
+#else
+template<typename T, unsigned SIZE, typename R1>
+inline VecBase<T,SIZE, meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary> >
+operator-(const VecBase<T,SIZE,R1>& v1)
+{
+   return VecBase<T,SIZE,
+                  meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary> >
+                        ( meta::VecUnaryExpr<VecBase<T,SIZE,R1>, meta::VecNegUnary>(v1) );
+}
+#endif
+
+/**
+ * Adds v2 to v1 and stores the result in v1. This is equivalent to the
+ * expression v1 = v1 + v2.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  v1 after v2 has been added to it
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE>
+VecBase<DATA_TYPE, SIZE>& operator +=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const VecBase<DATA_TYPE, SIZE>& v2)
+#else
+template<class DATA_TYPE, unsigned SIZE, typename REP2>
+VecBase<DATA_TYPE, SIZE>& operator +=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const VecBase<DATA_TYPE, SIZE, REP2>& v2)
+#endif
+{
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      v1[i] += v2[i];
+   }
+
+   return v1;
+}
+
+/**
+ * Adds v2 to v1 and returns the result. Thus result = v1 + v2.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  the result of adding v2 to v1
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE>
+VecBase<DATA_TYPE, SIZE> operator +(const VecBase<DATA_TYPE, SIZE>& v1,
+                                    const VecBase<DATA_TYPE, SIZE>& v2)
+{
+   VecBase<DATA_TYPE, SIZE> ret_val(v1);
+   ret_val += v2;
+   return ret_val;
+}
+#else
+template<typename T, unsigned SIZE, typename R1, typename R2>
+inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,R2>, meta::VecPlusBinary> >
+operator+(const VecBase<T,SIZE,R1>& v1, const VecBase<T,SIZE,R2>& v2)
+{
+   return VecBase<T,SIZE,
+               meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                   VecBase<T,SIZE,R2>,
+                                   meta::VecPlusBinary> >( meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                                               VecBase<T,SIZE,R2>,
+                                                                               meta::VecPlusBinary>(v1,v2) );
+}
+#endif
+
+/**
+ * Subtracts v2 from v1 and stores the result in v1. This is equivalent to the
+ * expression v1 = v1 - v2.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  v1 after v2 has been subtracted from it
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE>
+VecBase<DATA_TYPE, SIZE>& operator -=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const VecBase<DATA_TYPE, SIZE>& v2)
+#else
+template<class DATA_TYPE, unsigned SIZE, typename REP2>
+VecBase<DATA_TYPE, SIZE>& operator -=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const VecBase<DATA_TYPE, SIZE, REP2>& v2)
+#endif
+{
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      v1[i] -= v2[i];
+   }
+
+   return v1;
+}
+
+/**
+ * Subtracts v2 from v1 and returns the result. Thus result = v1 - v2.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  the result of subtracting v2 from v1
+ */
+#ifdef GMTL_NO_METAPROG
+template < class DATA_TYPE, unsigned SIZE>
+Vec<DATA_TYPE, SIZE> operator -(const VecBase<DATA_TYPE, SIZE>& v1,
+                                const VecBase<DATA_TYPE, SIZE>& v2)
+{
+   Vec<DATA_TYPE, SIZE> ret_val(v1);
+   ret_val -= v2;
+   return ret_val;
+}
+#else
+template<typename T, unsigned SIZE, typename R1, typename R2>
+inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE,R2>, meta::VecMinusBinary> >
+operator-(const VecBase<T,SIZE,R1>& v1, const VecBase<T,SIZE,R2>& v2)
+{
+   return VecBase<T,SIZE,
+               meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                   VecBase<T,SIZE,R2>,
+                                   meta::VecMinusBinary> >( meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                                               VecBase<T,SIZE,R2>,
+                                                                               meta::VecMinusBinary>(v1,v2) );
+}
+#endif
+
+/**
+ * Multiplies v1 by a scalar value and stores the result in v1. This is
+ * equivalent to the expression v1 = v1 * scalar.
+ *
+ * @param v1      the vector to scale
+ * @param scalar  the amount by which to scale v1
+ *
+ * @return  v1 after it has been mutiplied by scalar
+ */
+template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
+VecBase<DATA_TYPE, SIZE>& operator *=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const SCALAR_TYPE& scalar)
+{
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      v1[i] *= (DATA_TYPE)scalar;
+   }
+
+   return v1;
+}
+
+/**
+ * Multiplies v1 by a scalar value and returns the result. Thus result = v1 *
+ * scalar.
+ *
+ * @param v1      the vector to scale
+ * @param scalar  the amount by which to scale v1
+ *
+ * @return  the result of multiplying v1 by scalar
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
+VecBase<DATA_TYPE, SIZE> operator *(const VecBase<DATA_TYPE, SIZE>& v1,
+                                    const SCALAR_TYPE& scalar)
+{
+   VecBase<DATA_TYPE, SIZE> ret_val(v1);
+   ret_val *= scalar;
+   return ret_val;
+
+   //return VecBase<DATA_TYPE, SIZE>(v1) *= scalar;
+}
+#else
+template<typename T, unsigned SIZE, typename R1>
+inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE, meta::ScalarArg<T> >, meta::VecMultBinary> >
+operator*(const VecBase<T,SIZE,R1>& v1, const T scalar)
+{
+   return VecBase<T,SIZE,
+             meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                 VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                 meta::VecMultBinary> >(
+                                       meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                           VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                                           meta::VecMultBinary>(v1,
+                                                                                meta::ScalarArg<T>(scalar)) );
+}
+
+template<typename T, unsigned SIZE, typename R1>
+inline VecBase<T,SIZE, meta::VecBinaryExpr< VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                            VecBase<T,SIZE,R1>,
+                                            meta::VecMultBinary> >
+operator*(const T scalar, const VecBase<T,SIZE,R1>& v1)
+{
+   return VecBase<T,SIZE,
+             meta::VecBinaryExpr<VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                 VecBase<T,SIZE,R1>,
+                                 meta::VecMultBinary> >(
+                                       meta::VecBinaryExpr<VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                                           VecBase<T,SIZE,R1>,
+                                                           meta::VecMultBinary>(meta::ScalarArg<T>(scalar), v1 ) );
+}
+#endif
+
+/**
+ * Multiplies v1 by a scalar value and returns the result. Thus result = scalar
+ * * v1. This is equivalent to result = v1 * scalar.
+ *
+ * @param scalar  the amount by which to scale v1
+ * @param v1      the vector to scale
+ *
+ * @return  the result of multiplying v1 by scalar
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
+VecBase<DATA_TYPE, SIZE> operator *(const SCALAR_TYPE& scalar,
+                                    const VecBase<DATA_TYPE, SIZE>& v1)
+{
+   VecBase<DATA_TYPE, SIZE> ret_val(v1);
+   ret_val *= scalar;
+   return ret_val;
+
+   //return VecBase<DATA_TYPE, SIZE>(v1) *= scalar;
+}
+#endif
+
+/**
+ * Divides v1 by a scalar value and stores the result in v1. This is
+ * equivalent to the expression v1 = v1 / scalar.
+ *
+ * @param v1      the vector to scale
+ * @param scalar  the amount by which to scale v1
+ *
+ * @return  v1 after it has been divided by scalar
+ */
+template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
+VecBase<DATA_TYPE, SIZE>& operator /=(VecBase<DATA_TYPE, SIZE>& v1,
+                                      const SCALAR_TYPE& scalar)
+{
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      v1[i] /= scalar;
+   }
+
+   return v1;
+}
+
+/**
+ * Divides v1 by a scalar value and returns the result. Thus result = v1 /
+ * scalar.
+ *
+ * @param v1      the vector to scale
+ * @param scalar  the amount by which to scale v1
+ *
+ * @return  the result of dividing v1 by scalar
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE, class SCALAR_TYPE>
+VecBase<DATA_TYPE, SIZE> operator /(const VecBase<DATA_TYPE, SIZE>& v1,
+                                    const SCALAR_TYPE& scalar)
+{
+   VecBase<DATA_TYPE, SIZE> ret_val(v1);
+   ret_val /= scalar;
+   return ret_val;
+   // return VecBase<DATA_TYPE, SIZE>(v1)( /= scalar;
+}
+#else
+template<typename T, unsigned SIZE, typename R1>
+inline VecBase<T,SIZE, meta::VecBinaryExpr<VecBase<T,SIZE,R1>, VecBase<T,SIZE, meta::ScalarArg<T> >, meta::VecDivBinary> >
+operator/(const VecBase<T,SIZE,R1>& v1, const T scalar)
+{
+   return VecBase<T,SIZE,
+             meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                 VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                 meta::VecDivBinary> >(
+                                       meta::VecBinaryExpr<VecBase<T,SIZE,R1>,
+                                                           VecBase<T,SIZE, meta::ScalarArg<T> >,
+                                                           meta::VecDivBinary>(v1,
+                                                                               meta::ScalarArg<T>(scalar)) );
+}
+#endif
+
+/** @} */
+
+
+/** @ingroup Ops
+ *  @name Vector Operations
+ * @{
+ */
+
+/**
+ * Computes dot product of v1 and v2 and returns the result.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return the dotproduct of v1 and v2
+ */
+#ifdef GMTL_NO_METAPROG
+template<class DATA_TYPE, unsigned SIZE>
+DATA_TYPE dot(const VecBase<DATA_TYPE, SIZE>& v1, const VecBase<DATA_TYPE, SIZE>& v2)
+{
+   DATA_TYPE ret_val(0);
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      ret_val += (v1[i] * v2[i]);
+   }
+   return ret_val;
+}
+#else
+template<class DATA_TYPE, unsigned SIZE, typename REP1, typename REP2>
+DATA_TYPE dot(const VecBase<DATA_TYPE, SIZE, REP1>& v1, const VecBase<DATA_TYPE, SIZE, REP2>& v2)
+{
+   return gmtl::meta::DotVecUnrolled<SIZE-1,
+                                     VecBase<DATA_TYPE,SIZE,REP1>,
+                                     VecBase<DATA_TYPE,SIZE,REP2> >::func(v1,v2);
+}
+#endif
+
+/**
+ * Computes the length of the given vector.
+ *
+ * @param v1   the vector with which to compute the length
+ *
+ * @return  the length of v1
+ */
+template<class DATA_TYPE, unsigned SIZE>
+DATA_TYPE length(const Vec<DATA_TYPE, SIZE>& v1)
+{
+   DATA_TYPE ret_val = lengthSquared(v1);
+   if (ret_val == DATA_TYPE(0.0f))
+      return DATA_TYPE(0.0f);
+   else
+      return Math::sqrt(ret_val);
+}
+
+/**
+ * Computes the square of the length of the given vector. This can be used in
+ * many calculations instead of length to increase speed by saving you an
+ * expensive sqrt call.
+ *
+ * @param v1   the vector with which to compute the squared length
+ *
+ * @return  the square of the length of v1
+ */
+template<class DATA_TYPE, unsigned SIZE>
+DATA_TYPE lengthSquared(const Vec<DATA_TYPE, SIZE>& v1)
+{
+#ifdef GMTL_NO_METAPROG
+   DATA_TYPE ret_val(0);
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      ret_val += (v1[i] * v1[i]);
+   }
+
+   return ret_val;
+#else
+   return gmtl::meta::LenSqrVecUnrolled<SIZE-1,Vec<DATA_TYPE,SIZE> >::func(v1);
+#endif
+}
+
+/**
+ * Normalizes the given vector in place causing it to be of unit length. If the
+ * vector is already of length 1.0, nothing is done. For convenience, the
+ * original length of the vector is returned.
+ *
+ * @post length(v1) == 1.0 unless length(v1) is originally 0.0, in which case it is unchanged
+ *
+ * @param v1   the vector to normalize
+ *
+ * @return  the length of v1 before it was normalized
+ */
+template<class DATA_TYPE, unsigned SIZE>
+DATA_TYPE normalize(Vec<DATA_TYPE, SIZE>& v1)
+{
+   DATA_TYPE len = length(v1);
+
+   if(len != 0.0f)
+   {
+      for(unsigned i=0;i<SIZE;++i)
+      {
+         v1[i] /= len;
+      }
+   }
+
+   return len;
+}
+
+/**
+ * Determines if the given vector is normalized within the given tolerance. The
+ * vector is normalized if its lengthSquared is 1.
+ *
+ * @param v1      the vector to test
+ * @param eps     the epsilon tolerance
+ *
+ * @return  true if the vector is normalized, false otherwise
+ */
+template< class DATA_TYPE, unsigned SIZE >
+bool isNormalized( const Vec<DATA_TYPE, SIZE>& v1,
+                   const DATA_TYPE eps = (DATA_TYPE) 0.0001f )
+{
+   return Math::isEqual( lengthSquared( v1 ), DATA_TYPE(1.0), eps );
+}
+
+/**
+ * Computes the cross product between v1 and v2 and stores the result in result.
+ * The result is also returned by reference. Use this when you want to reuse an
+ * existing Vec to store the result. Note that this only applies to
+ * 3-dimensional vectors.
+ *
+ * @pre v1 and v2 are 3-D vectors
+ * @post result = v1 x v2
+ *
+ * @param result  filled with the result of the cross product between v1 and v2
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  a reference to result for convenience
+ */
+template<class DATA_TYPE>
+Vec<DATA_TYPE,3>& cross( Vec<DATA_TYPE,3>& result, const Vec<DATA_TYPE, 3>& v1,
+                         const Vec<DATA_TYPE, 3>& v2 )
+{
+   result.set( (v1[Yelt]*v2[Zelt]) - (v1[Zelt]*v2[Yelt]),
+               (v1[Zelt]*v2[Xelt]) - (v1[Xelt]*v2[Zelt]),
+               (v1[Xelt]*v2[Yelt]) - (v1[Yelt]*v2[Xelt]) );
+   return result;
+}
+
+/**
+ * Reflect a vector about a normal.
+ *
+ * This method reflects the given vector around the normal vector given.  It is similar to if the normal vector was
+ * for a plane that you wanted to reflect about.  v going into the plane, n normal to the plane, and r coming back out
+ * of the plane. (see below)
+ *
+ * |   v
+ * | /
+ * |/
+ * |------> n
+ * |\
+ * | \
+ * |  r
+ *
+ * @param result     the vector to store the result i
+ * @param vec        the original vector that we want to reflect
+ * @param normal     the normal vector
+ *
+ * @post result contains the reflected vector
+*/
+template<class DATA_TYPE, unsigned SIZE>
+VecBase<DATA_TYPE, SIZE>& reflect( VecBase<DATA_TYPE, SIZE>& result, const
+                           VecBase<DATA_TYPE, SIZE>& vec,
+                           const Vec<DATA_TYPE, SIZE>& normal )
+{
+   result = vec - (DATA_TYPE( 2.0 ) * (dot( (Vec<DATA_TYPE, SIZE>)vec, normal ) * normal));
+   return result;
+}
+
+/** @} */
+
+/** @ingroup Interp
+ * @name Vector Interpolation
+ * @{
+ */
+
+/**
+ * Linearly interpolates between to vectors.
+ *
+ * @pre  lerpVal is a value between 0 and 1 that interpolates between from and to.
+ * @post undefined if lerpVal < 0 or lerpVal > 1
+ *
+ * @param result     the result of the linear interpolation
+ * @param lerpVal    the value to interpolate between from and to
+ * @param from       the vector at lerpVal 0
+ * @param to         the vector at lerpVal 1
+ *
+ * @return  a reference to result for convenience
+ */
+template <typename DATA_TYPE, unsigned SIZE>
+VecBase<DATA_TYPE, SIZE>& lerp( VecBase<DATA_TYPE, SIZE>& result,
+                                const DATA_TYPE& lerpVal,
+                                const VecBase<DATA_TYPE, SIZE>& from,
+                                const VecBase<DATA_TYPE, SIZE>& to )
+{
+   /// @todo metaprogramming...
+   for (unsigned int x = 0; x < SIZE; ++x)
+   {
+      Math::lerp( result[x], lerpVal, from[x], to[x] );
+   }
+   return result;
+}
+/** @} */
+
+/** @ingroup Compare
+ * @name Vector Comparitors
+ * @{
+ */
+
+
+// --- VEC comparisons -- //
+
+/**
+ * Compares v1 and v2 to see if they are exactly the same.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  true if v1 equals v2; false if they differ
+ */
+template<class DATA_TYPE, unsigned SIZE>
+inline bool operator==(const VecBase<DATA_TYPE, SIZE>& v1,
+                       const VecBase<DATA_TYPE, SIZE>& v2)
+{
+#ifdef GMTL_NO_METAPROG
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      if(v1[i] != v2[i])
+      {
+         return false;
+      }
+   }
+
+   return true;
+#else
+   return gmtl::meta::EqualVecUnrolled<SIZE-1,Vec<DATA_TYPE,SIZE> >::func(v1,v2);
+#endif
+   /*  Would like this
+   return(vec[0] == _v[0] &&
+          vec[1] == _v[1] &&
+          vec[2] == _v[2]);
+          */
+}
+
+/**
+ * Compares v1 and v2 to see if they are NOT exactly the same with zero
+ * tolerance.
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ *
+ * @return  true if v1 does not equal v2; false if they are equal
+ */
+template<class DATA_TYPE, unsigned SIZE>
+inline bool operator!=(const VecBase<DATA_TYPE, SIZE>& v1,
+                       const VecBase<DATA_TYPE, SIZE>& v2)
+{
+   return(! (v1 == v2));
+}
+
+/**
+ * Compares v1 and v2 to see if they are the same within the given epsilon
+ * tolerance.
+ *
+ * @pre eps must be >= 0
+ *
+ * @param v1   the first vector
+ * @param v2   the second vector
+ * @param eps  the epsilon tolerance value
+ *
+ * @return  true if v1 equals v2 within the tolerance; false if they differ
+ */
+template<class DATA_TYPE, unsigned SIZE>
+inline bool isEqual(const VecBase<DATA_TYPE, SIZE>& v1,
+                    const VecBase<DATA_TYPE, SIZE>& v2, const DATA_TYPE eps)
+{
+   gmtlASSERT(eps >= 0);
+
+   for(unsigned i=0;i<SIZE;++i)
+   {
+      if ( gmtl::Math::abs(v1[i] - v2[i]) > eps )
+      {
+         return false;
+      }
+   }
+   return true;
+}
+
+/** @} */
+
+}
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/VecOpsMeta.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/VecOpsMeta.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/VecOpsMeta.h	(revision 4)
@@ -0,0 +1,102 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          VecOpsMeta.h,v
+ * Date modified: 2005/05/16 14:19:44
+ * Version:       1.3
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VEC_OPS_META_H
+#define _GMTL_VEC_OPS_META_H
+
+#include <gmtl/Util/Meta.h>
+
+/** Meta programming classes for vec operations
+ */
+namespace gmtl
+{
+namespace meta
+{
+/** @ingroup VecOpsMeta */
+//@{
+
+/** meta class to unroll dot products. */
+template<int ELT, typename T1, typename T2>
+struct DotVecUnrolled
+{
+   static typename T1::DataType func(const T1& v1, const T2& v2)
+   {  return (v1[ELT]*v2[ELT]) + DotVecUnrolled<ELT-1,T1,T2>::func(v1,v2); }
+};
+
+/** base cas for dot product unrolling. */
+template<typename T1, typename T2>
+struct DotVecUnrolled<0,T1,T2>
+{
+   static typename T1::DataType func(const T1& v1, const T2& v2)
+   {   return (v1[0]*v2[0]); }
+};
+
+/** meta class to unroll length squared operation. */
+template<int ELT, typename T>
+struct LenSqrVecUnrolled
+{
+   static typename T::DataType func(const T& v)
+   {  return (v[ELT]*v[ELT]) + LenSqrVecUnrolled<ELT-1,T>::func(v); }
+};
+
+/** base cas for dot product unrolling. */
+template<typename T>
+struct LenSqrVecUnrolled<0,T>
+{
+   static typename T::DataType func(const T& v)
+   {   return (v[0]*v[0]); }
+};
+
+/** meta class to test vector equality. */
+template<int ELT, typename VT>
+struct EqualVecUnrolled
+{
+   static bool func(const VT& v1, const VT& v2)
+   {  return (v1[ELT]==v2[ELT]) && EqualVecUnrolled<ELT-1,VT>::func(v1,v2); }
+};
+
+/** base cas for dot product unrolling. */
+template<typename VT>
+struct EqualVecUnrolled<0,VT>
+{
+   static bool func(const VT& v1, const VT& v2)
+   {   return (v1[0]==v2[0]); }
+};
+//@}
+
+} // namespace meta
+} // end namespace
+
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Version.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Version.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Version.h	(revision 4)
@@ -0,0 +1,173 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Version.h,v
+ * Date modified: 2006/11/10 21:55:50
+ * Version:       1.38.2.1
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_VERSION_H_
+#define _GMTL_VERSION_H_
+
+/**
+ * This file contains two useful items.
+ *    1. The preprocessor friendly GMTL_VERSION "string". It is in the form
+ *       <major><minor><patch> where each part has exactly 3 digits.
+ *    2. The C++ friendly variable, version, that contains the version as a
+ *       string. It is in the form of <major>.<minor>.<patch> where each part
+ *       has anywhere from 1 to 3 digits.
+ */
+
+/**
+ * This is the "human-readable" GMTL version _string_. It is of the form
+ * <major><minor><patch>. Each part has exactly 3 digits.
+ */
+// The major/minor/patch version (up to 3 digits each).
+#define GMTL_VERSION_MAJOR    0
+#define GMTL_VERSION_MINOR    4
+#define GMTL_VERSION_PATCH    12
+
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+// To update the version number, do not modify anything below this line!!!!
+//--------------------------------------------------------------------------
+//--------------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------------
+// Define the helper macros
+//--------------------------------------------------------------------------
+
+// These helper macros are used build up the GMTL_VERSION macro
+#define GMTL_GLUE(a,b)        a ## b
+#define GMTL_XGLUE(a,b)       GMTL_GLUE(a,b)
+
+// These helper macros are used to stringify a given macro
+#define GMTL_STR(s)           # s
+#define GMTL_XSTR(s)          GMTL_STR(s)
+
+// These helper macros are used to build up the GMTL_VERSION_STRING macro.
+#define GMTL_DOT(a,b)         a ## . ## b
+#define GMTL_XDOT(a,b)        GMTL_DOT(a,b)
+
+// These helpr macros are used to facilitate a zero left fill
+#define GMTL_ZEROFILL(a)      0 ## a
+#define GMTL_XZEROFILL(a)     GMTL_ZEROFILL(a)
+
+// Fix up the major version by doing a zero left fill
+#if GMTL_VERSION_MAJOR < 10
+#  define GMTL_VERSION_MAJOR_FILLED \
+               GMTL_XZEROFILL(GMTL_XZEROFILL(GMTL_VERSION_MAJOR))
+#elif GMTL_VERSION_MAJOR < 100
+#  define GMTL_VERSION_MAJOR_FILLED GMTL_XZEROFILL(GMTL_VERSION_MAJOR)
+#else
+#  define GMTL_VERSION_MAJOR_FILLED GMTL_VERSION_MAJOR
+#endif
+
+// Fix up the minor version by doing a zero left fill
+#if GMTL_VERSION_MINOR < 10
+#  define GMTL_VERSION_MINOR_FILLED \
+               GMTL_XZEROFILL(GMTL_XZEROFILL(GMTL_VERSION_MINOR))
+#elif GMTL_VERSION_MINOR < 100
+#  define GMTL_VERSION_MINOR_FILLED GMTL_XZEROFILL(GMTL_VERSION_MINOR)
+#else
+#  define GMTL_VERSION_MINOR_FILLED GMTL_VERSION_MINOR
+#endif
+
+// Fix up the patch version by doing a zero left fill
+#if GMTL_VERSION_PATCH < 10
+#  define GMTL_VERSION_PATCH_FILLED \
+               GMTL_XZEROFILL(GMTL_XZEROFILL(GMTL_VERSION_PATCH))
+#elif GMTL_VERSION_PATCH < 100
+#  define GMTL_VERSION_PATCH_FILLED GMTL_XZEROFILL(GMTL_VERSION_PATCH)
+#else
+#  define GMTL_VERSION_PATCH_FILLED GMTL_VERSION_PATCH
+#endif
+
+//--------------------------------------------------------------------------
+// Define the GMTL_VERSION and GMTL_VERSION_STRING macros
+//--------------------------------------------------------------------------
+
+// Build up the GMTL_VERSION macro by pasting the individual parts together
+/**
+ * The is the preprocessor-friendly version string. It is in the form of
+ * <major><minor><patch>. Each part has exactly 3 digits.
+ */
+#define GMTL_VERSION \
+   GMTL_XGLUE( \
+      GMTL_XGLUE(GMTL_VERSION_MAJOR_FILLED, GMTL_VERSION_MINOR_FILLED), \
+      GMTL_VERSION_PATCH_FILLED \
+   )
+
+// Create the GMTL_VERSION_STRING macro
+#define GMTL_VERSION_STRING \
+   GMTL_XDOT( \
+      GMTL_XDOT(GMTL_VERSION_MAJOR, GMTL_VERSION_MINOR), \
+      GMTL_VERSION_PATCH \
+   )
+
+//--------------------------------------------------------------------------
+// Declare a version string constant that can be used at runtime.
+//--------------------------------------------------------------------------
+namespace gmtl
+{
+   inline const char* getVersion()
+   {
+      return GMTL_XSTR(GMTL_VERSION_STRING);
+   }
+} // end namespace gmtl
+
+//--------------------------------------------------------------------------
+// Cleanup after ourselves and undef all internal macros.
+//--------------------------------------------------------------------------
+
+// Undef the all helper macros
+#undef GMTL_XGLUE
+#undef GMTL_GLUE
+#undef GMTL_XSTR
+#undef GMTL_STR
+#undef GMTL_ZEROFILL
+#undef GMTL_XZEROFILL
+#undef GMTL_XDOT
+#undef GMTL_DOT
+
+// Undef the GMTL_VERSION_STRING temporary macro
+#undef GMTL_VERSION_STRING
+
+// Undef the XXX_FILLED temporary macros
+#undef GMTL_VERSION_MAJOR_FILLED
+#undef GMTL_VERSION_MINOR_FILLED
+#undef GMTL_VERSION_PATCH_FILLED
+
+// Undef the macro for each version part
+#undef GMTL_VERSION_MAJOR
+#undef GMTL_VERSION_MINOR
+#undef GMTL_VERSION_PATCH
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/Xforms.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/Xforms.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/Xforms.h	(revision 4)
@@ -0,0 +1,537 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          Xforms.h,v
+ * Date modified: 2004/11/12 01:34:49
+ * Version:       1.34
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_XFORMS_H_
+#define _GMTL_XFORMS_H_
+
+#include <gmtl/Point.h>
+#include <gmtl/Vec.h>
+#include <gmtl/Matrix.h>
+#include <gmtl/MatrixOps.h>
+#include <gmtl/Quat.h>
+#include <gmtl/QuatOps.h>
+#include <gmtl/Ray.h>
+#include <gmtl/LineSeg.h>
+#include <gmtl/Util/StaticAssert.h>
+
+namespace gmtl
+{
+   /** @ingroup Transforms
+    *  @name Vector Transform (Quaternion)
+    *  @{
+    */
+   
+   /** transform a vector by a rotation quaternion.
+    * @pre give a vector, and a rotation quaternion (by definition, a rotation quaternion is normalized).
+    * @param result     The vector to write the result into
+    * @param rot        The quaternion
+    * @param vector     The original vector to transform
+    * @post v' = q P(v) q*  (where result is v', rot is q, and vector is v.  q* is conj(q), and P(v) is pure quaternion made from v)
+    * @see game programming gems #1 p199
+    * @see shoemake siggraph notes
+    * @notes for the implementation, inv and conj should both work for the "q*" in "Rv = q P(v) q*"
+    *        but conj is actually faster so we usually choose that.
+    * @notes also note, that if the input quat wasn't normalized (and thus isn't a rotation quat),
+    *        then this might not give the correct result, since conj and invert is only equiv when normalized...
+    */
+   template <typename DATA_TYPE>
+   inline VecBase<DATA_TYPE, 3>& xform( VecBase<DATA_TYPE, 3>& result, const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
+   {
+      // check preconditions...
+      gmtlASSERT( Math::isEqual( length( rot ), (DATA_TYPE)1.0, (DATA_TYPE)0.0001 ) && "must pass a rotation quaternion to xform(result,quat,vec) - by definition, a rotation quaternion is normalized).  if you need non-rotation quaternion support, let us know." );
+
+      // easiest to write and understand (slowest too)
+      //return result_vec = makeVec( rot * makePure( vector ) * makeConj( rot ) );
+
+      // completely hand expanded
+      // (faster by 28% in gcc 2.96 debug mode.)
+      // (faster by 35% in gcc 2.96 opt3 mode (78% for doubles))
+      Quat<DATA_TYPE> rot_conj( -rot[Xelt], -rot[Yelt], -rot[Zelt], rot[Welt] );
+      Quat<DATA_TYPE> pure( vector[0], vector[1], vector[2], (DATA_TYPE)0.0 );
+      Quat<DATA_TYPE> temp(
+         pure[Welt]*rot_conj[Xelt] + pure[Xelt]*rot_conj[Welt] + pure[Yelt]*rot_conj[Zelt] - pure[Zelt]*rot_conj[Yelt],
+         pure[Welt]*rot_conj[Yelt] + pure[Yelt]*rot_conj[Welt] + pure[Zelt]*rot_conj[Xelt] - pure[Xelt]*rot_conj[Zelt],
+         pure[Welt]*rot_conj[Zelt] + pure[Zelt]*rot_conj[Welt] + pure[Xelt]*rot_conj[Yelt] - pure[Yelt]*rot_conj[Xelt],
+         pure[Welt]*rot_conj[Welt] - pure[Xelt]*rot_conj[Xelt] - pure[Yelt]*rot_conj[Yelt] - pure[Zelt]*rot_conj[Zelt] );
+
+      result.set(
+         rot[Welt]*temp[Xelt] + rot[Xelt]*temp[Welt] + rot[Yelt]*temp[Zelt] - rot[Zelt]*temp[Yelt],
+         rot[Welt]*temp[Yelt] + rot[Yelt]*temp[Welt] + rot[Zelt]*temp[Xelt] - rot[Xelt]*temp[Zelt],
+         rot[Welt]*temp[Zelt] + rot[Zelt]*temp[Welt] + rot[Xelt]*temp[Yelt] - rot[Yelt]*temp[Xelt] );
+      return result;
+   }
+
+   /** transform a vector by a rotation quaternion.
+    * @pre give a vector, and a rotation quaternion (by definition, a rotation quaternion is normalized).
+    * @param rot        The quaternion
+    * @param vector     The original vector to transform
+    * @return  the resulting vector transformed by the quaternion
+    * @post v' = q P(v) q*  (where result is v', rot is q, and vector is v.  q* is conj(q), and P(v) is pure quaternion made from v)
+    */
+   template <typename DATA_TYPE>
+   inline VecBase<DATA_TYPE, 3> operator*( const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
+   {
+      VecBase<DATA_TYPE, 3> temporary;
+      return xform( temporary, rot, vector );
+   }
+
+
+   /** transform a vector by a rotation quaternion.
+    * @pre give a vector, and a rotation quaternion (by definition, a rotation quaternion is normalized).
+    * @param rot        The quaternion
+    * @param vector     The original vector to transform
+    * @post v' = q P(v) q*  (where result is v', rot is q, and vector is v.  q* is conj(q), and P(v) is pure quaternion made from v)
+    */   
+   template <typename DATA_TYPE>
+   inline VecBase<DATA_TYPE, 3> operator*=(VecBase<DATA_TYPE, 3>& vector, const Quat<DATA_TYPE>& rot)
+   {
+      VecBase<DATA_TYPE, 3> temporary = vector;
+      return xform( vector, rot, temporary);
+   }
+
+
+   /** @} */
+
+   /** @ingroup Transforms
+    *  @name Vector Transform (Matrix)
+    *  @{
+    */
+
+   /** xform a vector by a matrix.
+    *  Transforms a vector with a matrix, uses multiplication of [m x k] matrix by a [k x 1] matrix (the later also known as a Vector...).
+    *  @param result        the vector to write the result in
+    *  @param matrix        the transform matrix
+    *  @param vector        the original vector
+    *  @post This results in a rotational xform of the vector (assumes you know what you are doing -
+    *  i.e. that you know that the last component of a vector by definition is 0.0, and changing
+    *  this might make the xform different than what you may expect).
+    *  @post returns a point same size as the matrix rows...  (v[r][1] = m[r][k] * v[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Vec<DATA_TYPE, COLS>& xform( Vec<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
+   {
+      // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
+
+      // reset vec to zero...
+      result = Vec<DATA_TYPE, COLS>();
+
+      for (unsigned iRow = 0; iRow < ROWS; ++iRow)
+      for (unsigned iCol = 0; iCol < COLS; ++iCol)
+         result[iRow] += matrix( iRow, iCol ) * vector[iCol];
+
+      return result;
+   }
+
+
+   /** matrix * vector xform.
+    *  multiplication of [m x k] matrix by a [k x 1] matrix (also known as a Vector...).
+    *  @param matrix    the transform matrix
+    *  @param vector    the original vector
+    *  @return  the vector transformed by the matrix
+    *  @post This results in a full matrix xform of the vector (assumes you know what you are doing -
+    *  i.e. that you know that the last component of a vector by definition is 0.0, and changing
+    *  this might make the xform different that what you may expect).
+    *  @post returns a vec same size as the matrix rows...  (v[r][1] = m[r][k] * v[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Vec<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
+   {
+      // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
+      Vec<DATA_TYPE, COLS> temporary;
+      return xform( temporary, matrix, vector );
+   }
+
+
+
+
+   /** partially transform a partially specified vector by a matrix, assumes last elt of vector is 0 (the 0 makes it only partially transformed).
+    *  Transforms a vector with a matrix, uses multiplication of [m x k] matrix by a [k-1 x 1] matrix (also known as a Vector [with w == 0 for vectors by definition] ).
+    *  @param result        the vector to write the result in
+    *  @param matrix        the transform matrix
+    *  @param vector        the original vector
+    *  @post the [k-1 x 1] vector you pass in is treated as a [vector, 0.0]
+    *  @post This ends up being a partial xform using only the rotation from the matrix (vector xformed result is untranslated).
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned VEC_SIZE>
+   inline Vec<DATA_TYPE, VEC_SIZE>& xform( Vec<DATA_TYPE, VEC_SIZE >& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, VEC_SIZE >& vector )
+   {
+      GMTL_STATIC_ASSERT( VEC_SIZE == COLS - 1, Vec_of_wrong_size_for_xform );
+      // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
+
+      // copy the point to the correct size.
+      Vec<DATA_TYPE, COLS> temp_vector, temp_result;
+      for (unsigned x = 0; x < VEC_SIZE; ++x)
+         temp_vector[x] = vector[x];
+      temp_vector[COLS-1] = (DATA_TYPE)0.0; // by definition of a vector, set the last unspecified elt to 0.0
+
+      // transform it.
+      xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_vector );
+
+      // convert result back to vec<DATA_TYPE, VEC_SIZE>
+      // some matrices will make the W param large even if this is a true vector,
+      // we'll need to redistribute it to the other elts if W param is non-zero
+      if (Math::isEqual( temp_result[VEC_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
+      {
+         DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[VEC_SIZE];
+         for (unsigned x = 0; x < VEC_SIZE; ++x)
+            result[x] = temp_result[x] * w_coord_div;
+      }
+      else
+      {
+         for (unsigned x = 0; x < VEC_SIZE; ++x)
+            result[x] = temp_result[x];
+      }
+
+      return result;
+   }
+
+   /** matrix * partial vector, assumes last elt of vector is 0 (partial transform).
+    *  @param matrix        the transform matrix
+    *  @param vector        the original vector
+    *  @return  the vector transformed by the matrix
+    *  multiplication of [m x k] matrix by a [k-1 x 1] matrix (also known as a Vector [with w == 0 for vectors by definition] ).
+    *  @post the [k-1 x 1] vector you pass in is treated as a [vector, 0.0]
+    *  @post This ends up being a partial xform using only the rotation from the matrix (vector xformed result is untranslated).
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
+   inline Vec<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS_MINUS_ONE>& vector )
+   {
+      Vec<DATA_TYPE, COLS_MINUS_ONE> temporary;
+      return xform( temporary, matrix, vector );
+   }
+
+   /** @} */
+
+   /** @ingroup Transforms
+    *  @name Point Transform (Matrix)
+    *  @{
+    */
+
+
+   /** transform point by a matrix.
+    *  multiplication of [m x k] matrix by a [k x 1] matrix (also known as a Point...).
+    *  @param result        the point to write the result in
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @post This results in a full matrix xform of the point.
+    *  @post returns a point same size as the matrix rows...  (p[r][1] = m[r][k] * p[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Point<DATA_TYPE, COLS>& xform( Point<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
+   {
+      // do a standard [m x k] by [k x n] matrix multiplication (n == 1).
+
+      // reset point to zero...
+      result = Point<DATA_TYPE, COLS>();
+
+      for (unsigned iRow = 0; iRow < ROWS; ++iRow)
+      for (unsigned iCol = 0; iCol < COLS; ++iCol)
+         result[iRow] += matrix( iRow, iCol ) * point[iCol];
+
+      return result;
+   }
+
+   /** matrix * point.
+    *  multiplication of [m x k] matrix by a [k x 1] matrix (also known as a Point...).
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @return  the point transformed by the matrix
+    *  @post This results in a full matrix xform of the point.
+    *  @post returns a point same size as the matrix rows...  (p[r][1] = m[r][k] * p[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Point<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
+   {
+      Point<DATA_TYPE, COLS> temporary;
+      return xform( temporary, matrix, point );
+   }
+
+
+
+
+   /** transform a partially specified point by a matrix, assumes last elt of point is 1.
+    *  Transforms a point with a matrix, uses multiplication of [m x k] matrix by a [k-1 x 1] matrix (also known as a Point [with w == 1 for points by definition] ).
+    *  @param result        the point to write the result in
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @post the [k-1 x 1] point you pass in is treated as [point, 1.0]
+    *  @post This results in a full matrix xform of the point.
+    * @todo we need a PointOps.h operator*=(scalar) function
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned PNT_SIZE>
+   inline Point<DATA_TYPE, PNT_SIZE>& xform( Point<DATA_TYPE, PNT_SIZE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, PNT_SIZE>& point )
+   {
+      //gmtlSERT( PNT_SIZE == COLS - 1 && "The precondition of this method is that the vector size must be one less than the number of columns in the matrix.  eg. if Mat<n,k>, then Vec<k-1>." );
+      GMTL_STATIC_ASSERT( PNT_SIZE == COLS-1, Point_not_of_size_mat_col_minus_1_as_required_for_xform);
+
+      // copy the point to the correct size.
+      Point<DATA_TYPE, PNT_SIZE+1> temp_point, temp_result;
+      for (unsigned x = 0; x < PNT_SIZE; ++x)
+         temp_point[x] = point[x];
+      temp_point[PNT_SIZE] = (DATA_TYPE)1.0; // by definition of a point, set the last unspecified elt to 1.0
+
+      // transform it.
+      xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_point );
+
+      // convert result back to pnt<DATA_TYPE, PNT_SIZE>
+      // some matrices will make the W param large even if this is a true vector,
+      // we'll need to redistribute it to the other elts if W param is non-zero
+      if (Math::isEqual( temp_result[PNT_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
+      {
+         DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[PNT_SIZE];
+         for (unsigned x = 0; x < PNT_SIZE; ++x)
+            result[x] = temp_result[x] * w_coord_div;
+      }
+      else
+      {
+         for (unsigned x = 0; x < PNT_SIZE; ++x)
+            result[x] = temp_result[x];
+      }
+
+      return result;
+   }
+
+   /** matrix * partially specified point.
+    *  multiplication of [m x k] matrix by a [k-1 x 1] matrix (also known as a Point [with w == 1 for points by definition] ).
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @return  the point transformed by the matrix
+    *  @post the [k-1 x 1] vector you pass in is treated as a [point, 1.0]
+    *  @post This results in a full matrix xform of the point.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
+   inline Point<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS_MINUS_ONE>& point )
+   {
+      Point<DATA_TYPE, COLS_MINUS_ONE> temporary;
+      return xform( temporary, matrix, point );
+   }
+
+   /** point * a matrix
+    *  multiplication of [m x k] matrix by a [k x 1] matrix (also known as a Point [with w == 1 for points by definition] ).
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @return  the point transformed by the matrix
+    *  @post This results in a full matrix xform of the point.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Point<DATA_TYPE, COLS> operator*( const Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
+   {
+      Point<DATA_TYPE, COLS> temporary;
+      return xform( temporary, matrix, point );
+   }
+
+
+   /** point *= a matrix
+    *  multiplication of [m x k] matrix by a [k x 1] matrix (also known as a Point [with w == 1 for points by definition] ).
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @return  the point transformed by the matrix
+    *  @post This results in a full matrix xform of the point.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Point<DATA_TYPE, COLS> operator*=(Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix)
+   {
+      Point<DATA_TYPE, COLS> temporary = point;
+      return xform( point, matrix, temporary);
+   }
+
+   /** partial point *= a matrix
+    *  multiplication of [m x k] matrix by a [k-1 x 1] matrix (also known as a Point [with w == 1 for points by definition] ).
+    *  @param matrix        the transform matrix
+    *  @param point         the original point
+    *  @return  the point transformed by the matrix
+    *  @post the [k-1 x 1] vector you pass in is treated as a [point, 1.0]
+    *  @post This results in a full matrix xform of the point.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
+   inline Point<DATA_TYPE, COLS_MINUS_ONE>& operator*=( Point<DATA_TYPE, COLS_MINUS_ONE>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
+   {
+      Point<DATA_TYPE, COLS_MINUS_ONE> temporary = point;
+      return xform( point, matrix, temporary);
+   }
+
+
+   /** @} */
+
+   /** transform ray by a matrix.
+    *  multiplication of [m x k] matrix by two [k x 1] matrices (also known as a ray...).
+    *  @param result        the ray to write the result in
+    *  @param matrix        the transform matrix
+    *  @param ray           the original ray
+    *  @post This results in a full matrix xform of the ray.
+    *  @post returns a ray same size as the matrix rows...  (p[r][1] = m[r][k] * p[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Ray<DATA_TYPE>& xform( Ray<DATA_TYPE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Ray<DATA_TYPE>& ray )
+   {
+      gmtl::Point<DATA_TYPE, 3> pos;
+      gmtl::Vec<DATA_TYPE, 3> dir;
+      result.setOrigin( xform( pos, matrix, ray.getOrigin() ) );
+      result.setDir( xform( dir, matrix, ray.getDir() ) );
+      return result;
+   }
+
+   /** ray * a matrix
+    *  multiplication of [m x k] matrix by a ray.
+    *  @param matrix        the transform matrix
+    *  @param ray           the original ray
+    *  @return  the ray transformed by the matrix
+    *  @post This results in a full matrix xform of the ray.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Ray<DATA_TYPE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Ray<DATA_TYPE>& ray )
+   {
+      Ray<DATA_TYPE> temporary;
+      return xform( temporary, matrix, ray );
+   }
+
+
+   /** ray *= a matrix
+    *  multiplication of [m x k] matrix by a ray.
+    *  @param matrix        the transform matrix
+    *  @param ray           the original ray
+    *  @return  the ray transformed by the matrix
+    *  @post This results in a full matrix xform of the ray.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline Ray<DATA_TYPE>& operator*=( Ray<DATA_TYPE>& ray, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
+   {
+      Ray<DATA_TYPE> temporary = ray;
+      return xform( ray, matrix, temporary);
+   }
+
+   /** transform seg by a matrix.
+    *  multiplication of [m x k] matrix by two [k x 1] matrices (also known as a seg...).
+    *  @param result        the seg to write the result in
+    *  @param matrix        the transform matrix
+    *  @param seg           the original seg
+    *  @post This results in a full matrix xform of the seg.
+    *  @post returns a seg same size as the matrix rows...  (p[r][1] = m[r][k] * p[k][1])
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline LineSeg<DATA_TYPE>& xform( LineSeg<DATA_TYPE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const LineSeg<DATA_TYPE>& seg )
+   {
+      gmtl::Point<DATA_TYPE, 3> pos;
+      gmtl::Vec<DATA_TYPE, 3> dir;
+      result.setOrigin( xform( pos, matrix, seg.getOrigin() ) );
+      result.setDir( xform( dir, matrix, seg.getDir() ) );
+      return result;
+   }
+
+   /** seg * a matrix
+    *  multiplication of [m x k] matrix by a seg.
+    *  @param matrix        the transform matrix
+    *  @param seg         the original ray
+    *  @return  the seg transformed by the matrix
+    *  @post This results in a full matrix xform of the seg.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline LineSeg<DATA_TYPE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const LineSeg<DATA_TYPE>& seg )
+   {
+      LineSeg<DATA_TYPE> temporary;
+      return xform( temporary, matrix, seg );
+   }
+
+
+   /** seg *= a matrix
+    *  multiplication of [m x k] matrix by a seg.
+    *  @param matrix        the transform matrix
+    *  @param seg         the original point
+    *  @return  the point transformed by the matrix
+    *  @post This results in a full matrix xform of the point.
+    */
+   template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
+   inline LineSeg<DATA_TYPE>& operator*=( LineSeg<DATA_TYPE>& seg, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
+   {
+      LineSeg<DATA_TYPE> temporary = seg;
+      return xform( seg, matrix, temporary);
+   }
+
+
+
+
+   // old xform stuff...
+/*
+// XXX: Assuming that there is no projective portion to the matrix or homogeneous coord
+// NOTE: It is a vec, so we don't deal with the translation
+Vec3 operator*(const Matrix& mat, const Vec3& vec)
+{
+
+   Vec3 ret_vec;
+   for(int iRow=0;iRow<3;iRow++)
+   {
+      ret_vec[iRow] = (vec[0]* (mat[0][iRow]))
+                    + (vec[1]* (mat[1][iRow]))
+                    + (vec[2]* (mat[2][iRow]));
+   }
+   return ret_vec;
+}
+
+// XXX: Assuming no projective or homogeneous coord to the mat
+Point3 operator*(const Matrix& mat, const Point3& point)
+{
+   Point3 ret_pt;
+   for(int iRow=0;iRow<3;iRow++)
+   {
+      ret_pt[iRow] = (point[0]* (mat[0][iRow]))
+                   + (point[1]* (mat[1][iRow]))
+                   + (point[2]* (mat[2][iRow]))
+                   + (mat[3][iRow]);
+   }
+   return ret_pt;
+}
+
+// Xform an OOB by a matrix
+// NOTE: This will NOT work if the matrix has shear or scale
+OOBox operator*(const Matrix& mat, const OOBox& box)
+{
+   OOBox ret_box;
+
+   ret_box.center() = mat * box.center();
+
+   ret_box.axis(0) = mat * ret_box.axis(0);
+   ret_box.axis(1) = mat * ret_box.axis(1);
+   ret_box.axis(2) = mat * ret_box.axis(2);
+
+   ret_box.halfLen(0) = box.halfLen(0);
+   ret_box.halfLen(1) = box.halfLen(1);
+   ret_box.halfLen(2) = box.halfLen(2);
+
+   return ret_box;
+}
+*/
+
+};
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.doxygen
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.doxygen	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.doxygen	(revision 4)
@@ -0,0 +1,150 @@
+/** @mainpage Generic Math Template Library
+ *  @section Using Using This Reference Guide
+ *  Welcome to GMTL.  To use this reference guide effectively, we suggest 
+ *  you see the <a href="modules.html">Modules</a> section first.
+ *  The <a href="modules.html">Modules</a> section provides the most 
+ *  intuitive navigation of the reference guide because this
+ *  section is structured very similar GMTL.  Be sure 
+ *  to read the GMTL Programmer's Guide (available on the 
+ *  <a href="http://ggt.sf.net">GMTL web site</a>) to 
+ *  understand the philosophy behind GMTL.  Understanding abstractly what 
+ *  GMTL is and why it is designed this way will make
+ *  your life with GMTL very easy.  Lastly, you should subscribe to the mailing
+ *  lists so that you can ask questions, or propose extensions to the library.
+ *
+ *  Please see the @ref gmtlfaq "GMTL FAQ"  for more information.
+ *
+ *  @section API Quickly Understanding The GMTL API
+ *  The GMTL API has two aspects you should keep in mind. The <i>data</i>
+ *  types, and the <i>operations</i> on the data.
+ *  <p>
+ *  All data types and operations are defined in the <tt>gmtl</tt>
+ *  namespace.
+ *  Thus all types must be prefixed with the <tt>gmtl::</tt>
+ *  scope or a <tt>using gmtl;</tt> command can be used to bring all
+ *  of the GMTL functionality into the local scope.
+ *
+ *  @subsection Types Supplied GMTL Math Types
+ *  GMTL comes with many math data types: Vec, Point, Matrix, Quat, Coord, 
+ *  Sphere.
+ *  Please read the programmer's guide for more detailed information.
+ *  Or read on for a light overview on what GMTL is.
+ *
+ *  @section Overview A Light Overview Of GMTL
+ *  GMTL stands for (<b>G</b>)eneric (<b>M</b>)ath
+ *  (<b>T</b>)emplate (<b>L</b>)ibrary. 
+ *  It is a math library designed to be high-performance, 
+ *  extensible, and generic. The design is based upon discussion with many 
+ *  experts in the field of computer graphics and virtual reality and is the 
+ *  culmination of many previous graphics math library efforts. GMTL gives 
+ *  the graphics programmer several core math types and a rich library of 
+ *  graphics/math operations on those types.
+ *  
+ *  @subsection Design Design
+ *  The design of GMTL allows extensibility while mantaining a stable core.
+ *  Core data types are separated from operations. This allows anyone to write
+ *  their own math routines to extend or replace parts of the GMTL. This 
+ *  feature
+ *  allows a very stable core set of math primitives that seldom change due to
+ *  extensions, maintainance, or programmer error.
+ *  <p>
+ *  All math primitives in GMTL use generic programming techniques
+ *  to give the programmer many options to define their data. For example, 
+ *  matrices
+ *  and vectors can be any dimension and any type. GMTL suffers no loss of 
+ *  performance
+ *  due to these generalities because the parameter choices made are bound 
+ *  at <i>compile time</i>.
+ *
+ *  @subsection Implementation Implementation
+ *  GMTL is implemented using generic programming and template metaprogramming.
+ *  Generic
+ *  programming allows selection by the user of size and type information for 
+ *  all
+ *  data types in GMTL. For example, the generic Matrix type allows a 
+ *  programmer
+ *  to select between any size (N x M) and any datatype (float, double, 
+ *  int...).
+ *  The selection of these parameters is done through <i>template
+ *  parameters</i>. To ease the use of these parameters, the system declares
+ *  several typedefs that capture commonly used options.
+ *  <p>
+ *  Requested data types are statically bound and optimized by the compiler.
+ *  The operations supplied with GMTL are implemented generically using a 
+ *  technique
+ *  called <i>template metaprogramming</i>. Template metaprogramming
+ *  allows things such as loops to be unrolled and conditionals to be 
+ *  evaluated
+ *  <i>by the compiler</i>. Things such as loops and conditionals are
+ *  evaluated statically, rather than at runtime. In addition, advanced 
+ *  optimizations
+ *  can be performed that do this such as eliminate temporary variables and 
+ *  other
+ *  intermediate computations. The result is compiled code that can behave as
+ *  fast
+ *  (or faster) then using traditional hand-coding methods such as loop 
+ *  unrolling, etc...
+ *
+ *  @subsection Testing Testing
+ *  GMTL has an integrated test suite included in the source code distribution.
+ *  The suite tests GMTL for correctness as well as performance degradation.
+ *  The GMTL developers have put much time and effort into the test suite 
+ *  because
+ *  we think that it will ensure that the code stays stable when changes are 
+ *  made,
+ *  and that changes don't introduce performance hits. The bottom line is, 
+ *  if any
+ *  behaviour changes in GMTL we want to know about it before it bites us. 
+ *  As a result
+ *  of this philosophy, any contributions to GMTL also need to be well 
+ *  tested.
+ *  Submissions will not be accepted without tests for correctness and 
+ *  performance.
+ *
+ *        
+ */
+ 
+/** @defgroup Defines Global Flags: Xelt, XYZ, etc...
+ *  Constant Static Global Flags
+ */
+ 
+/** @defgroup Math C Math Abstraction: sin, cos, tan, Min, Max, PI
+ *  We've abstracted C math to be cross platform and typesafe.
+ */
+
+/** @defgroup Types Abstract Data Types: Matrix, Vec, Quat, Coord, Sphere, Plane
+ *  GMTL comes with many math data types: Vec, Point, Matrix, Quat, Coord, Sphere.
+ */
+
+
+
+/** @defgroup Ops Mathematical Operations: add(...), sub(...), mul(...), div(...), invert(...), dot(...), cross(...)
+ *  Implements fundamental mathematical operations such as +, -, *, invert, dot product.
+ */
+
+/** @defgroup Transforms Spacial Transformers: xform( ... ), operator*( ... ).
+ *  Transform points and vectors by Matrices and Quaternions.  Note that xform
+ *  is defined differently for Point and Vec.  By Point is a full xform, by Vec 
+ *  is only a rotation.
+ */
+
+/** @defgroup Compare Comparison: isEqual(...), isEquiv(...), ==, !=
+ *  Tests for equality between GMTL data types.
+ */
+
+/** @defgroup Generate Generators: make( ... ), set( ... ).
+ *  Make get and set functions for all math types in gmtl.
+ */
+
+/** @defgroup Interp Interpolation: lerp(...), slerp(...)
+ *  Functions to interpolate between two values.
+ */
+ 
+
+/** @defgroup Output Output Stream Methods: operator<<( ... ). 
+ *  Output GMTL data types to an ostream.  std::ostream& operator<< methods...
+ */
+
+
+/** @defgroup Meta Template Metaprogramming Utilities */
+/** @defgroup HelperMeta Template Metaprogramming Utilities (Helpers) */
Index: projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gmtl/gmtl.h	(revision 4)
@@ -0,0 +1,72 @@
+/************************************************************** ggt-head beg
+ *
+ * GGT: Generic Graphics Toolkit
+ *
+ * Original Authors:
+ *   Allen Bierbaum
+ *
+ * -----------------------------------------------------------------
+ * File:          gmtl.h,v
+ * Date modified: 2003/03/15 21:19:38
+ * Version:       1.9
+ * -----------------------------------------------------------------
+ *
+ *********************************************************** ggt-head end */
+/*************************************************************** ggt-cpr beg
+*
+* GGT: The Generic Graphics Toolkit
+* Copyright (C) 2001,2002 Allen Bierbaum 
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+ ************************************************************ ggt-cpr end */
+#ifndef _GMTL_GMTL_H_
+#define _GMTL_GMTL_H_
+
+#include <gmtl/AABox.h>
+#include <gmtl/AABoxOps.h>
+#include <gmtl/AxisAngle.h>
+#include <gmtl/AxisAngleOps.h>
+#include <gmtl/Containment.h>
+#include <gmtl/Coord.h>
+#include <gmtl/CoordOps.h>
+#include <gmtl/Defines.h>
+#include <gmtl/EulerAngle.h>
+#include <gmtl/EulerAngleOps.h>
+#include <gmtl/Generate.h>
+#include <gmtl/Intersection.h>
+#include <gmtl/LineSeg.h>
+#include <gmtl/LineSegOps.h>
+#include <gmtl/Math.h>
+#include <gmtl/Matrix.h>
+#include <gmtl/MatrixOps.h>
+#include <gmtl/Output.h>
+#include <gmtl/Plane.h>
+#include <gmtl/PlaneOps.h>
+#include <gmtl/Point.h>
+#include <gmtl/Quat.h>
+#include <gmtl/QuatOps.h>
+#include <gmtl/Ray.h>
+#include <gmtl/Sphere.h>
+#include <gmtl/SphereOps.h>
+#include <gmtl/Tri.h>
+#include <gmtl/TriOps.h>
+#include <gmtl/VecBase.h>
+#include <gmtl/Vec.h>
+#include <gmtl/VecOps.h>
+#include <gmtl/Version.h>
+#include <gmtl/Xforms.h>
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gui/Defines.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/Defines.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/Defines.h	(revision 4)
@@ -0,0 +1,12 @@
+#ifndef _GUI_DEFINES_H_
+#define _GUI_DEFINES_H_
+
+#include <QString>
+
+namespace projection
+{
+QString formatValue(double value);
+double  formatValue(const QString& value);
+};
+
+#endif // _GUI_DEFINES_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QChannelManagerWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QChannelManagerWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QChannelManagerWidget.h	(revision 4)
@@ -0,0 +1,58 @@
+#ifndef _QCHANNELMANAGERWIDGET_H_
+#define _QCHANNELMANAGERWIDGET_H_
+
+#include <QtGui>
+#include <QtXml>
+
+#include "ui_qchannelmanagerwidget.h"
+
+namespace projection
+{
+class ProjectionModel;
+class Channel;
+
+class QChannelManagerWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QChannelManagerWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    virtual ~QChannelManagerWidget();
+
+    void setModel(ProjectionModel* pModel);
+
+    void selectChannel(int index);
+    int getSelectedChannel() const;
+
+    bool initFromDOMElement(const QDomElement& element);
+    QDomElement domElement(QDomDocument& doc) const;
+
+public slots:
+
+    void updateChannelNamesGUI();
+    void updateGUI();
+
+private slots:
+
+    void on_addButton_clicked();
+    void on_removeButton_clicked();
+    void on_channelTable_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn);
+    void on_channelTable_itemChanged(QTableWidgetItem* pItem);
+    void channelTableHeaderClicked(int index);
+    void channelStateChanged();
+
+private:
+
+    void addChannelToTable(int row, Channel* pChannel);
+
+private:
+
+    Ui::QChannelManagerWidget ui;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QCHANNELMANAGERWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QChannelWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QChannelWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QChannelWidget.h	(revision 4)
@@ -0,0 +1,61 @@
+#ifndef _QCHANNELWIDGET_H_
+#define _QCHANNELWIDGET_H_
+
+#include <QtGui>
+
+#include "Frustum.h"
+#include "interfaces.h"
+
+#include "ui_qchannelwidget.h"
+
+namespace projection
+{
+class Channel;
+
+class QChannelWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QChannelWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QChannelWidget();
+
+    void setChannel(Channel* pChannel);
+    Channel* getChannel() const;
+
+public slots:
+
+    void updateGUI();
+
+	void on_projectionTransformWidget_matrixChanged(const TransformMatrix& TM);
+	void on_viewProjectionWidget_matrixChanged(const ProjectionMatrix& matrix);
+	void on_viewTransformWidget_matrixChanged(const TransformMatrix& matrix);
+
+private slots:
+
+    void on_nameEdit_editingFinished();
+    void on_overlayNameCheckBox_toggled(bool checked);
+    void on_remoteHostNameEdit_editingFinished();
+    void on_remoteFullScreenCheckBox_toggled(bool checked);
+    void on_remoteScreenComboBox_activated(int index);
+    void on_overlayImageEdit_editingFinished();
+    void on_overlayImageBrowseButton_clicked();
+    void on_warpCheckBox_toggled(bool checked);
+    void on_warpResSpinBox_valueChanged(int value);
+    void on_warpResetButton_clicked();
+    void on_calibrateButton_clicked();
+    void on_fitButton_clicked();
+    void on_windowButton_clicked();
+	void on_pluginComboBox_currentIndexChanged(int index);
+
+private:
+
+    Ui::QChannelWidget ui;
+
+    Channel* m_pChannel;
+};
+
+}; // projection
+
+#endif // _QCHANNELWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QClientWindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QClientWindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QClientWindow.h	(revision 4)
@@ -0,0 +1,33 @@
+#ifndef _QCLIENTWINDOW_H_
+#define _QCLIENTWINDOW_H_
+
+#include <QtGui>
+
+#include "ui_qclientwindow.h"
+
+namespace projection
+{
+
+class QClientWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+
+    QClientWindow(QWidget* pParent=0, Qt::WFlags flags=0);
+    ~QClientWindow();
+
+    void appendLog(const QString& line);
+
+private slots:
+
+    void on_actionFileExit_triggered();
+
+private:
+
+    Ui::QClientWindow ui;
+};
+
+}; // projection
+
+#endif // _QCLIENTWINDOW_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWidget.h	(revision 4)
@@ -0,0 +1,88 @@
+#ifndef _QDESIGNVIEWWIDGET_H_
+#define _QDESIGNVIEWWIDGET_H_
+
+#include "gui/QGLViewerWidget.h"
+
+namespace projection
+{
+class ProjectionModel;
+class Channel;
+
+enum DESIGN_VIEWMODE
+{
+    DESIGN_VIEWMODE_PERSPECTIVE,
+    DESIGN_VIEWMODE_CENTER,
+    DESIGN_VIEWMODE_TOP,
+    DESIGN_VIEWMODE_SIDE,
+    DESIGN_VIEWMODE_FRONT
+};
+
+enum DESIGN_OPMODE
+{
+    DESIGN_OPMODE_PROJECTOR,
+    DESIGN_OPMODE_VIEW
+};
+
+enum DESIGN_TRANSMODE
+{
+    DESIGN_TRANSMODE_LOCAL,
+    DESIGN_TRANSMODE_WORLD
+};
+
+class QDesignViewWidget : public QGLViewerWidget
+{
+    Q_OBJECT
+
+public:
+
+    QDesignViewWidget(QWidget* pParent=0, const QGLWidget* pSharedWidget=0, Qt::WFlags flags=0);
+    virtual ~QDesignViewWidget();
+
+	void setModel(ProjectionModel* pModel);
+
+    void setViewMode(DESIGN_VIEWMODE viewMode);
+    DESIGN_VIEWMODE getViewMode() const;
+
+    void setOpMode(DESIGN_OPMODE opMode);
+    DESIGN_OPMODE getOpMode() const;
+
+    void setTransMode(DESIGN_TRANSMODE transMode);
+    DESIGN_TRANSMODE getTransMode() const;
+
+	void setInfoVisible(bool bVisible);
+	bool isInfoVisible() const;
+
+	void setFont(QFont font);
+	QFont getFont() const;
+
+    virtual void keyReleaseEvent(QKeyEvent* pEvent);
+
+    void processChannelKeyEvent(Channel* pChannel, QKeyEvent* pEvent);
+
+    virtual void initFromDOMElement(const QDomElement& element);
+    virtual QDomElement domElement(QDomDocument& doc) const;
+
+signals:
+
+    void infoVisibilityChanged(bool bVisible);
+
+protected:
+
+    virtual void init();
+    virtual void draw();
+
+protected:
+
+	bool m_bInfoVisible;
+
+    DESIGN_VIEWMODE m_viewMode;
+    DESIGN_OPMODE m_opMode;
+    DESIGN_TRANSMODE m_transMode;
+    QFont m_infoFont;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QDESIGNVIEWWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QDesignViewWindow.h	(revision 4)
@@ -0,0 +1,98 @@
+#ifndef _QDESIGNVIEWWINDOW_H_
+#define _QDESIGNVIEWWINDOW_H_
+
+#include <QtGui>
+#include <QtXml>
+#include <QDir>
+
+#include "ui_qdesignviewwindow.h"
+
+namespace projection
+{
+class ProjectionModel;
+class QDesignViewWidget;
+class QPanelWidget;
+class Channel;
+
+class QDesignViewWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+
+    QDesignViewWindow(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QDesignViewWindow();
+
+	void setModel(ProjectionModel* pModel);
+
+    QGLWidget* getGLWidget() const;
+    QDesignViewWidget* getDesignView() const;
+    QPanelWidget* getPanel() const;
+
+    bool loadFile(const QString& fileName);
+    bool saveFile(const QString& fileName);
+
+    void initFromDOMElement(const QDomElement& element);
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+private slots:
+
+    void on_actionFileNew_triggered();
+	void on_actionFileOpen_triggered();
+	void on_actionFileSave_triggered();
+	void on_actionFileSaveAs_triggered();
+	void on_actionFileExportDataset_triggered();
+	void on_actionFileSyncClients_triggered();
+    void on_actionFileExit_triggered();
+    void on_actionFileExitAll_triggered();
+	void on_actionEditDesignDistortionMap_triggered();
+	void on_actionEditDesignBlendMap_triggered();
+	void on_actionEditPreference_triggered();
+    void on_menuEdit_aboutToShow();
+	void on_actionViewPerspective_triggered();
+	void on_actionViewCenter_triggered();
+	void on_actionViewTop_triggered();
+	void on_actionViewSide_triggered();
+	void on_actionViewFront_triggered();
+    void on_menuView_aboutToShow();
+	void on_actionViewAxis_triggered(bool checked);
+	void on_designViewWidget_axisVisibilityChanged(bool bVisible);
+	void on_actionViewGrid_triggered(bool checked);
+	void on_designViewWidget_gridVisibilityChanged(bool bVisible);
+	void on_actionViewInfo_triggered(bool checked);
+	void on_designViewWidget_infoVisibilityChanged(bool bVisible);
+	void on_actionViewViewAll_triggered();
+	void on_actionWindowSceneViewer_triggered();
+	void on_actionWindowSceneDialog_triggered();
+	void on_actionWindowScreenDialog_triggered();
+	void on_actionWindowChannelManager_triggered();
+	void on_actionHelpHelp_triggered();
+	void on_actionHelpAbout_triggered();
+	void on_actionHelpAbout_Qt_triggered();
+	void on_actionHelpPlugins_triggered();
+
+    void setCurrentFile(const QString& fileName);
+    void updateRecentFileActions();
+    void openRecentFile();
+
+    void activateDesignView();
+
+protected:
+    virtual void closeEvent (QCloseEvent* pEvent);
+
+private:
+
+    Ui::QDesignViewWindow ui;
+
+    // file history management
+    QString m_fileName;
+    enum { MAX_RECENT_FILES = 5 };
+    QAction* m_pRecentFileActs[MAX_RECENT_FILES];
+    QAction* m_pSeparatorAct;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QDESIGNVIEWWINDOW_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QGLViewerWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QGLViewerWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QGLViewerWidget.h	(revision 4)
@@ -0,0 +1,129 @@
+#ifndef _QGLVIEWERWIDGET_H_
+#define _QGLVIEWERWIDGET_H_
+
+#include <QtXml>
+#include <QGLWidget>
+#include <QTimer>
+#include <QTime>
+
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+
+class QGLViewerWidget : public QGLWidget
+{
+    Q_OBJECT
+
+public:
+
+    QGLViewerWidget(QWidget* pParent=0, const QGLWidget* pShareWidget=0, Qt::WindowFlags f=0);
+
+    void setClearColor(const QColor& color) { m_clearColor = color; }
+    QColor clearColor() const { return m_clearColor; }
+
+    void setView(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance);
+
+    void setPerspective(bool bPerspective) { m_bPerspective = bPerspective; }
+    bool isPerspective() const { return m_bPerspective; }
+
+    void setFovy(float fovy) { m_fovy = fovy; }
+    float fovy() const { return m_fovy; }
+
+    void setZNear(float znear) { m_znear = znear; }
+    float znear() const { return m_znear; }
+
+    void setZFar(float zfar) { m_zfar = zfar; }
+    float zfar() const { return m_zfar; }
+
+    void setGridVisible(bool bVisible) { if (bVisible != m_bGridVisible) {  m_bGridVisible = bVisible; emit gridVisibilityChanged(bVisible); } }
+    bool isGridVisible() const { return m_bGridVisible; }
+
+    void setAxisVisible(bool bVisible) { if (bVisible != m_bAxisVisible) {  m_bAxisVisible = bVisible; emit axisVisibilityChanged(bVisible); } }
+    bool isAxisVisible() const { return m_bAxisVisible; }
+
+    void setSceneSize(float sceneSize) { m_sceneSize = sceneSize; }
+    float sceneSize() const { return m_sceneSize; }
+
+    void setGridSize(float gridSize) { m_gridSize = gridSize; }
+    float gridSize() const { return m_gridSize; }
+
+    void setGridSubdivision(int subdiv) { m_gridSubdiv = subdiv; }
+    float gridSubdivision() const { return m_gridSubdiv; }
+
+    void centerView();
+    void viewAll();
+    void stop();
+
+    void setInertia(bool bInertia) { m_bInertia = bInertia; if (!m_bInertia) stop(); }
+    bool isInertia() const { return m_bInertia; }
+
+    bool isAnimating() const { return m_bAnimating; }
+
+    void initFromDOMElement(const QDomElement& element);
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    virtual void init();
+    virtual void draw();
+    virtual void idle();
+
+    virtual void initializeGL();
+    virtual void paintGL();
+    virtual void mousePressEvent(QMouseEvent* pEvent);
+    virtual void mouseMoveEvent(QMouseEvent* pEvent);
+    virtual void mouseReleaseEvent(QMouseEvent* pEvent);
+    virtual void wheelEvent(QWheelEvent* pEvent);
+    virtual void keyReleaseEvent(QKeyEvent* pEvent);
+
+    void drawGrid();
+    void drawAxis();
+
+protected slots:
+
+    void timeout();
+
+signals:
+
+    void cameraChanged(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance);
+    void axisVisibilityChanged(bool bVisible);
+    void gridVisibilityChanged(bool bVisible);
+
+protected:
+
+    QColor m_clearColor;
+
+    gmtl::Matrix44f m_matrix;
+    gmtl::Vec3f m_center;
+    gmtl::Quatf m_rot;
+    float m_distance;
+    float m_orthoScale;
+
+    gmtl::Vec3f m_pivotCenter;
+    gmtl::Quatf m_pivotRot;
+    float m_pivotDistance;
+    float m_pivotOrthoScale;
+
+    bool m_bPerspective;
+    float m_fovy;
+    float m_znear;
+    float m_zfar;
+
+    QPoint m_lastMousePos;
+    QTime m_lastTime;
+
+    bool m_bInertia;
+    float m_animX;
+    float m_animY;
+    bool m_bAnimating;
+
+    bool m_bGridVisible;
+    bool m_bAxisVisible;
+
+    float m_sceneSize;
+    float m_gridSize;
+    int m_gridSubdiv;
+
+    QTimer m_timer;
+};
+
+#endif // _QGLVIEWERWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QPanelWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QPanelWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QPanelWidget.h	(revision 4)
@@ -0,0 +1,44 @@
+#ifndef _QPANELWIDGET_H_
+#define _QPANELWIDGET_H_
+
+#include <QtGui>
+
+#include "ui_qpanelwidget.h"
+
+namespace projection
+{
+class ProjectionModel;
+class Channel;
+
+class QPanelWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QPanelWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QPanelWidget();
+
+    void setModel(ProjectionModel* pModel);
+    void selectChannel(Channel* pChannel);
+    void removeChannel(Channel* pChannel);
+
+    void activateChannels();
+    void activateScreen();
+    void activateScene();
+
+    void updateChannelNames();
+    void updateChannels();
+    void updateCurrentChannel();
+    void updateGUI();
+
+private:
+
+    Ui::QPanelWidget ui;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QPANELWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QPreferenceDialog.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QPreferenceDialog.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QPreferenceDialog.h	(revision 4)
@@ -0,0 +1,53 @@
+#ifndef _QPREFERENCEDIALOG_H_
+#define _QPREFERENCEDIALOG_H_
+
+#include <QtGui>
+
+#include "ui_qpreferencedialog.h"
+
+namespace projection
+{
+class ProjectionModel;
+class QDesignViewWidget;
+
+class QPreferenceDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+
+    QPreferenceDialog(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QPreferenceDialog();
+
+    void setModel(ProjectionModel* pModel);
+
+    void updateGUI();
+
+private slots:
+
+    void on_gridSizeEdit_editingFinished();
+    void on_gridSubdivSpinBox_valueChanged(int value);
+
+    void on_bufferWidthComboBox_activated(int);
+    void on_bufferHeightComboBox_activated(int);
+
+	void on_exportWidthComboBox_activated(int);
+	void on_exportHeightComboBox_activated(int);
+    void on_softEdgeCheckBox_toggled(bool checked);
+    void on_blendEdgeWidthSpinBox_valueChanged(int value);
+    void on_blendEdgeExponentEdit_editingFinished();
+    void on_exportDistortMapPatternEdit_editingFinished();
+    void on_exportBlendMapPatternEdit_editingFinished();
+    void on_exportViewMatrixPatternEdit_editingFinished();
+
+private:
+
+    Ui::QPreferenceDialog ui;
+    QDesignViewWidget* m_pDesignView;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QPREFERENCEDIALOG_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QProjectionMatrixWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QProjectionMatrixWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QProjectionMatrixWidget.h	(revision 4)
@@ -0,0 +1,51 @@
+#ifndef _QPROJECTIONMATRIXWIDGET_H_
+#define _QPROJECTIONMATRIXWIDGET_H_
+
+#include <QtGui>
+
+#include "math/ProjectionMatrix.h"
+
+#include "ui_qprojectionmatrixwidget.h"
+
+namespace projection
+{
+
+class QProjectionMatrixWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QProjectionMatrixWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QProjectionMatrixWidget();
+
+    void setMatrix(const ProjectionMatrix& matrix);
+    ProjectionMatrix getMatrix() const;
+
+    void clear();
+
+signals:
+
+    void matrixChanged(const ProjectionMatrix& matrix);
+
+private slots:
+
+    void on_fovEdit_editingFinished();
+    void on_aspectRatioEdit_editingFinished();
+    void on_nearEdit_editingFinished();
+    void on_farEdit_editingFinished();
+    void on_offaxisXEdit_editingFinished();
+    void on_offaxisYEdit_editingFinished();
+    void checkValueChanged();
+
+private:
+
+    Ui::QProjectionMatrixWidget ui;
+
+    ProjectionMatrix m_matrix;
+    bool m_bStopSlot;       //??
+};
+
+}; // projection
+
+#endif // _QPROJECTIONMATRIXWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QProjectorWindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QProjectorWindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QProjectorWindow.h	(revision 4)
@@ -0,0 +1,57 @@
+#ifndef _QPROJECTORWINDOW_H_
+#define _QPROJECTORWINDOW_H_
+
+#include <QtXml>
+#include <QGLWidget>
+
+namespace projection
+{
+class ProjectionModel;
+class Channel;
+
+class QProjectorWindow : public QGLWidget
+{
+    Q_OBJECT
+
+public:
+
+    QProjectorWindow(QWidget* pParent=0, QGLWidget* pSharedWidget=0, Qt::WFlags flag=0);
+    virtual ~QProjectorWindow();
+
+    void setModel(ProjectionModel* pModel);
+
+    void setChannel(Channel* pChannel);
+    Channel* getChannel() const { return m_pChannel; }
+
+	void updateTitle();
+
+	void initFromDOMElement(const QDomElement& element);
+	QDomElement domElement(QDomDocument& document) const;
+
+protected:
+
+    virtual void initializeGL();
+    virtual void resizeGL(int width, int height);
+    virtual void paintGL();
+	virtual void keyReleaseEvent(QKeyEvent* pEvent);
+    virtual void mousePressEvent(QMouseEvent* pEvent);
+    virtual void mouseMoveEvent(QMouseEvent* pEvent);
+    virtual void wheelEvent(QWheelEvent* pEvent);
+    virtual void closeEvent(QCloseEvent* pEvent);
+
+protected:
+
+    Channel* m_pChannel;
+    QFont m_overlayFont;
+    QFont m_infoFont;
+
+    unsigned int m_blendChannelIndex;
+
+    static bool m_bInitialized;
+
+    ProjectionModel* m_pModel;
+};
+
+}; // projection
+
+#endif // _QPROJECTORWINDOW_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QSceneViewerWindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QSceneViewerWindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QSceneViewerWindow.h	(revision 4)
@@ -0,0 +1,49 @@
+#ifndef _QSCENEVIEWERWINDOW_H_
+#define _QSCENEVIEWERWINDOW_H_
+
+#include "gui/QGLViewerWidget.h"
+
+namespace projection
+{
+class ProjectionModel;
+
+enum SCENEVIEWER_VIEWMODE
+{
+    SCENEVIEWER_VIEWMODE_PERSPECTIVE,
+    SCENEVIEWER_VIEWMODE_CENTER,
+};
+
+class QSceneViewerWindow : public QGLViewerWidget
+{
+	Q_OBJECT
+
+public:
+
+    QSceneViewerWindow(QWidget* pParent=0, const QGLWidget* pSharedWidget=0, Qt::WFlags flags=0);
+
+    void setModel(ProjectionModel* pModel);
+
+    void setViewMode(SCENEVIEWER_VIEWMODE viewMode);
+    SCENEVIEWER_VIEWMODE getViewMode() const;
+
+    void resetCamera();
+
+    void initFromDOMElement(const QDomElement& element);
+	QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    virtual void init();
+    virtual void draw();
+    virtual void keyReleaseEvent(QKeyEvent* pEvent);
+
+protected:
+
+    SCENEVIEWER_VIEWMODE m_viewMode;
+
+    ProjectionModel* m_pModel;
+};
+
+};
+
+#endif // _QSCENEVIEWERWINDOW_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QSceneWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QSceneWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QSceneWidget.h	(revision 4)
@@ -0,0 +1,47 @@
+#ifndef _QSCENEWIDGET_H_
+#define _QSCENEWIDGET_H_
+
+#include <QtGui>
+
+#include "ui_qscenewidget.h"
+
+namespace projection
+{
+class Scene;
+
+class QSceneWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QSceneWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QSceneWidget();
+
+    void setScene(Scene* pScene);
+
+    void updateGUI();
+
+private slots:
+
+    void on_transformWidget_matrixChanged(const TransformMatrix& matrix);
+    void on_typeComboBox_activated(int);
+
+    void on_showInDesignViewCheckBox_toggled(bool checked);
+    void on_sceneSizeEdit_editingFinished();
+    void on_gridCheckBox_toggled(bool checked);
+    void on_gridSizeEdit_editingFinished();
+
+    void on_centerViewButton_clicked();
+    void on_viewAllButton_clicked();
+
+private:
+
+    Ui::QSceneWidget ui;
+
+    Scene* m_pScene;
+};
+
+}; // projection
+
+#endif // _QSCENEWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QScreenWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QScreenWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QScreenWidget.h	(revision 4)
@@ -0,0 +1,64 @@
+#ifndef _QSCREENWIDGET_H_
+#define _QSCREENWIDGET_H_
+
+#include <QtGui>
+
+#include "ui_qscreenwidget.h"
+
+namespace projection
+{
+class Screen;
+
+class QScreenWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QScreenWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QScreenWidget();
+
+    void setScreen(Screen* pScreen);
+
+    void updateGUI();
+
+private slots:
+
+    void on_typeComboBox_activated(int index);
+
+    void on_transformWidget_matrixChanged(const TransformMatrix& matrix);
+
+    void on_domeRadiusEdit_editingFinished();
+    void on_domeAzimResSpinBox_valueChanged(int value);
+    void on_domeElevResSpinBox_valueChanged(int value);
+    void on_domeSubdivSpinBox_valueChanged(int value);
+    void on_domeFullDomeCheckBox_toggled(bool checked);
+
+    void on_planeWidthEdit_editingFinished();
+    void on_planeHeightEdit_editingFinished();
+    void on_planeHorResSpinBox_valueChanged(int value);
+    void on_planeVertResSpinBox_valueChanged(int value);
+
+    void on_boxWidthEdit_editingFinished();
+    void on_boxHeightEdit_editingFinished();
+    void on_boxDepthEdit_editingFinished();
+    void on_boxHorResSpinBox_valueChanged(int value);
+    void on_boxVertResSpinBox_valueChanged(int value);
+    void on_boxDepthResSpinBox_valueChanged(int value);
+
+    void on_modelFileNameEdit_editingFinished();
+    void on_modelBrowseButton_clicked();
+
+    void on_frameCheckBox_toggled(bool checked);
+    void on_frameLineWidthSpinBox_valueChanged(int value);
+
+private:
+
+    Ui::QScreenWidget ui;
+
+    Screen* m_pScreen;
+};
+
+}; // projection
+
+#endif // _QSCREENWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/QTransformMatrixWidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/QTransformMatrixWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/QTransformMatrixWidget.h	(revision 4)
@@ -0,0 +1,57 @@
+#ifndef _QTRANSFORMMATRIXWIDGET_H_
+#define _QTRANSFORMMATRIXWIDGET_H_
+
+#include <QtGui>
+
+#include "math/TransformMatrix.h"
+
+#include "ui_qtransformmatrixwidget.h"
+
+namespace projection
+{
+
+class QTransformMatrixWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    QTransformMatrixWidget(QWidget* pParent=0, Qt::WFlags flag=0);
+    ~QTransformMatrixWidget();
+
+    void setMatrix(const TransformMatrix& matrix);
+    TransformMatrix getMatrix() const;
+
+    void setUseScale(bool bUseScale);
+
+    void clear();
+
+signals:
+
+    void matrixChanged(const TransformMatrix& matrix);
+
+private slots:
+
+    void on_posXEdit_editingFinished();
+    void on_posYEdit_editingFinished();
+    void on_posZEdit_editingFinished();
+    void on_rotHEdit_editingFinished();
+    void on_rotPEdit_editingFinished();
+    void on_rotREdit_editingFinished();
+    void on_scaleXEdit_editingFinished();
+    void on_scaleYEdit_editingFinished();
+    void on_scaleZEdit_editingFinished();
+
+    void checkValueChanged();
+
+private:
+
+    Ui::QTransformMatrixWidget ui;
+
+    TransformMatrix m_matrix;
+    bool m_bStopSlot;               //??
+};
+
+}; // projection
+
+#endif // _QTRANSFORMMATRIXWIDGET_H_
Index: projectionDesigner/trunk/projdesigner/include/gui/plugindialog.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/plugindialog.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/plugindialog.h	(revision 4)
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
+**
+** This file is part of the example classes of the Qt Toolkit.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef PLUGINDIALOG_H
+#define PLUGINDIALOG_H
+
+#include <QDialog>
+#include <QIcon>
+
+class QLabel;
+class QPushButton;
+class QStringList;
+class QTreeWidget;
+class QTreeWidgetItem;
+
+class PluginDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    PluginDialog(const QString &path, const QStringList &fileNames,
+                 QWidget *parent = 0);
+
+private:
+    void findPlugins(const QString &path, const QStringList &fileNames);
+    void populateTreeWidget(QObject *plugin, const QString &text);
+    void addItems(QTreeWidgetItem *pluginItem, const char *interfaceName,
+                  const QStringList &features);
+
+    QLabel *label;
+    QTreeWidget *treeWidget;
+    QPushButton *okButton;
+    QIcon interfaceIcon;
+    QIcon featureIcon;
+};
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/gui/qchannelmanagerwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qchannelmanagerwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qchannelmanagerwidget.ui	(revision 4)
@@ -0,0 +1,93 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QChannelManagerWidget</class>
+ <widget class="QWidget" name="QChannelManagerWidget" >
+  <property name="geometry" >
+   <rect>
+	<x>0</x>
+	<y>0</y>
+	<width>223</width>
+	<height>236</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Channel Manager</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+	<number>0</number>
+   </property>
+   <property name="spacing" >
+	<number>6</number>
+   </property>
+   <item>
+	<layout class="QVBoxLayout" >
+	 <property name="margin" >
+	  <number>0</number>
+	 </property>
+	 <property name="spacing" >
+	  <number>6</number>
+	 </property>
+	 <item>
+	  <widget class="QTableWidget" name="channelTable" >
+	   <property name="selectionMode" >
+		<enum>QAbstractItemView::SingleSelection</enum>
+	   </property>
+	   <property name="selectionBehavior" >
+		<enum>QAbstractItemView::SelectRows</enum>
+	   </property>
+	  </widget>
+	 </item>
+	 <item>
+	  <layout class="QHBoxLayout" >
+	   <property name="margin" >
+		<number>0</number>
+	   </property>
+	   <property name="spacing" >
+		<number>6</number>
+	   </property>
+	   <item>
+		<spacer>
+		 <property name="orientation" >
+		  <enum>Qt::Horizontal</enum>
+		 </property>
+		 <property name="sizeHint" >
+		  <size>
+		   <width>16</width>
+		   <height>20</height>
+		  </size>
+		 </property>
+		</spacer>
+	   </item>
+	   <item>
+		<widget class="QPushButton" name="addButton" >
+		 <property name="focusPolicy" >
+		  <enum>Qt::NoFocus</enum>
+		 </property>
+		 <property name="text" >
+		  <string>Add</string>
+		 </property>
+		</widget>
+	   </item>
+	   <item>
+		<widget class="QPushButton" name="removeButton" >
+		 <property name="focusPolicy" >
+		  <enum>Qt::NoFocus</enum>
+		 </property>
+		 <property name="text" >
+		  <string>Remove</string>
+		 </property>
+		</widget>
+	   </item>
+	  </layout>
+	 </item>
+	</layout>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qchannelwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qchannelwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qchannelwidget.ui	(revision 4)
@@ -0,0 +1,609 @@
+<ui version="4.0" >
+ <class>QChannelWidget</class>
+ <widget class="QWidget" name="QChannelWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>232</width>
+    <height>508</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Channel Settings</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="nameLabel" >
+       <property name="text" >
+        <string>Name</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="nameEdit" />
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="overlayGroupBox" >
+     <property name="title" >
+      <string>Overlay</string>
+     </property>
+     <layout class="QHBoxLayout" >
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <property name="margin" >
+       <number>4</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QCheckBox" name="overlayNameCheckBox" >
+          <property name="text" >
+           <string>Channel name</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="overlayImageLabel" >
+            <property name="text" >
+             <string>Image</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="overlayImageEdit" >
+            <property name="sizePolicy" >
+             <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="overlayImageBrowseButton" >
+            <property name="sizePolicy" >
+             <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize" >
+             <size>
+              <width>23</width>
+              <height>16777215</height>
+             </size>
+            </property>
+            <property name="text" >
+             <string>...</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolBox" name="toolBox" >
+     <property name="autoFillBackground" >
+      <bool>true</bool>
+     </property>
+     <property name="currentIndex" >
+      <number>1</number>
+     </property>
+     <widget class="QWidget" name="page" >
+      <property name="geometry" >
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>232</width>
+        <height>198</height>
+       </rect>
+      </property>
+      <attribute name="label" >
+       <string>Remote Settings</string>
+      </attribute>
+      <layout class="QHBoxLayout" >
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <item>
+          <layout class="QHBoxLayout" >
+           <property name="spacing" >
+            <number>6</number>
+           </property>
+           <property name="margin" >
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="remoteHostNameLabel" >
+             <property name="text" >
+              <string>Host name</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="remoteHostNameEdit" />
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" >
+           <property name="spacing" >
+            <number>6</number>
+           </property>
+           <property name="margin" >
+            <number>0</number>
+           </property>
+           <item>
+            <widget class="QCheckBox" name="remoteFullScreenCheckBox" >
+             <property name="text" >
+              <string>Full screen</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="remoteScreenLabel" >
+             <property name="text" >
+              <string> Screen</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QComboBox" name="remoteScreenComboBox" >
+             <item>
+              <property name="text" >
+               <string>1</string>
+              </property>
+             </item>
+             <item>
+              <property name="text" >
+               <string>2</string>
+              </property>
+             </item>
+             <item>
+              <property name="text" >
+               <string>3</string>
+              </property>
+             </item>
+             <item>
+              <property name="text" >
+               <string>4</string>
+              </property>
+             </item>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0" >
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="page_2" >
+      <property name="geometry" >
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>232</width>
+        <height>262</height>
+       </rect>
+      </property>
+      <attribute name="label" >
+       <string>Projector</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="spacing" >
+        <number>0</number>
+       </property>
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="pluginLabel" >
+           <property name="text" >
+            <string>Plugin</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="pluginComboBox" />
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0" >
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QStackedWidget" name="stackedWidget" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>150</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="projection::QTransformMatrixWidget" native="1" name="projectionTransformWidget" >
+         <property name="focusPolicy" >
+          <enum>Qt::StrongFocus</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="warpGroupBox" >
+         <property name="title" >
+          <string>Warp</string>
+         </property>
+         <layout class="QHBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>4</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QCheckBox" name="warpCheckBox" >
+              <property name="text" >
+               <string>Enable</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="warpResLabel" >
+              <property name="text" >
+               <string>Res.</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="warpResSpinBox" >
+              <property name="maximumSize" >
+               <size>
+                <width>32</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="minimum" >
+               <number>2</number>
+              </property>
+              <property name="maximum" >
+               <number>8</number>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="warpResetButton" >
+              <property name="maximumSize" >
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text" >
+               <string>Reset</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="spacing" >
+          <number>0</number>
+         </property>
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0" >
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="calibrateButton" >
+           <property name="enabled" >
+            <bool>false</bool>
+           </property>
+           <property name="text" >
+            <string>Calibrate...</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="page_3" >
+      <property name="geometry" >
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>232</width>
+        <height>349</height>
+       </rect>
+      </property>
+      <attribute name="label" >
+       <string>View</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="spacing" >
+        <number>0</number>
+       </property>
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="spacing" >
+          <number>0</number>
+         </property>
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="projection::QProjectionMatrixWidget" native="1" name="viewProjectionWidget" >
+           <property name="focusPolicy" >
+            <enum>Qt::StrongFocus</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="projection::QTransformMatrixWidget" native="1" name="viewTransformWidget" >
+           <property name="focusPolicy" >
+            <enum>Qt::StrongFocus</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <layout class="QHBoxLayout" >
+           <property name="spacing" >
+            <number>0</number>
+           </property>
+           <property name="margin" >
+            <number>0</number>
+           </property>
+           <item>
+            <spacer>
+             <property name="orientation" >
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0" >
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item>
+            <widget class="QPushButton" name="fitButton" >
+             <property name="enabled" >
+              <bool>false</bool>
+             </property>
+             <property name="text" >
+              <string>Fit to Projector</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0" >
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Fixed</enum>
+     </property>
+     <property name="sizeHint" stdset="0" >
+      <size>
+       <width>190</width>
+       <height>16</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="windowButton" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="focusPolicy" >
+        <enum>Qt::NoFocus</enum>
+       </property>
+       <property name="text" >
+        <string>Open Window...</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QTransformMatrixWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QTransformMatrixWidget.h</header>
+  </customwidget>
+  <customwidget>
+   <class>projection::QProjectionMatrixWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QProjectionMatrixWidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>nameEdit</tabstop>
+  <tabstop>remoteHostNameEdit</tabstop>
+  <tabstop>remoteFullScreenCheckBox</tabstop>
+  <tabstop>remoteScreenComboBox</tabstop>
+  <tabstop>windowButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qclientwindow.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qclientwindow.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qclientwindow.ui	(revision 4)
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QClientWindow</class>
+ <widget class="QMainWindow" name="QClientWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>344</width>
+    <height>254</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Designer</string>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QHBoxLayout" >
+    <property name="margin" >
+     <number>2</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item>
+     <widget class="QTextEdit" name="logEdit" >
+      <property name="acceptDrops" >
+       <bool>false</bool>
+      </property>
+      <property name="readOnly" >
+       <bool>true</bool>
+      </property>
+      <property name="acceptRichText" >
+       <bool>false</bool>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menuBar" >
+   <property name="geometry" >
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>344</width>
+     <height>18</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_File" >
+    <property name="title" >
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionFileExit" />
+   </widget>
+   <addaction name="menu_File" />
+  </widget>
+  <action name="actionFileExit" >
+   <property name="text" >
+    <string>E&amp;xit</string>
+   </property>
+  </action>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qdesignviewwindow.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qdesignviewwindow.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qdesignviewwindow.ui	(revision 4)
@@ -0,0 +1,399 @@
+<ui version="4.0" >
+ <class>QDesignViewWindow</class>
+ <widget class="QMainWindow" name="QDesignViewWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>960</width>
+    <height>700</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Designer</string>
+  </property>
+  <property name="windowIcon" >
+   <iconset resource="../../projdesigner.qrc" >
+    <normaloff>:/new/prefix1/Resources/projDesigner.png</normaloff>:/new/prefix1/Resources/projDesigner.png</iconset>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QHBoxLayout" >
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <property name="margin" >
+     <number>0</number>
+    </property>
+    <item>
+     <widget class="QSplitter" name="splitter" >
+      <property name="orientation" >
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="projection::QDesignViewWidget" native="1" name="designViewWidget" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="MinimumExpanding" hsizetype="Ignored" >
+         <horstretch>1</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+      <widget class="projection::QPanelWidget" native="1" name="panelWidget" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="MinimumExpanding" hsizetype="Preferred" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menuBar" >
+   <property name="geometry" >
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>960</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuEdit" >
+    <property name="title" >
+     <string>&amp;Edit</string>
+    </property>
+    <addaction name="actionEditDesignDistortionMap" />
+    <addaction name="actionEditDesignBlendMap" />
+    <addaction name="separator" />
+    <addaction name="actionEditPreference" />
+   </widget>
+   <widget class="QMenu" name="menuView" >
+    <property name="title" >
+     <string>&amp;View</string>
+    </property>
+    <addaction name="actionViewPerspective" />
+    <addaction name="actionViewCenter" />
+    <addaction name="actionViewFront" />
+    <addaction name="actionViewTop" />
+    <addaction name="actionViewSide" />
+    <addaction name="separator" />
+    <addaction name="actionViewAxis" />
+    <addaction name="actionViewGrid" />
+    <addaction name="actionViewInfo" />
+    <addaction name="separator" />
+    <addaction name="actionViewViewAll" />
+   </widget>
+   <widget class="QMenu" name="menuWindow" >
+    <property name="title" >
+     <string>&amp;Window</string>
+    </property>
+    <addaction name="actionWindowSceneViewer" />
+    <addaction name="separator" />
+    <addaction name="actionWindowSceneDialog" />
+    <addaction name="actionWindowScreenDialog" />
+    <addaction name="actionWindowChannelManager" />
+   </widget>
+   <widget class="QMenu" name="menuFile" >
+    <property name="title" >
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionFileNew" />
+    <addaction name="actionFileOpen" />
+    <addaction name="actionFileSave" />
+    <addaction name="actionFileSaveAs" />
+    <addaction name="separator" />
+    <addaction name="actionFileExportDataset" />
+    <addaction name="separator" />
+    <addaction name="actionFileSyncClients" />
+   </widget>
+   <widget class="QMenu" name="menuHelp" >
+    <property name="title" >
+     <string>&amp;Help</string>
+    </property>
+    <addaction name="actionHelpHelp" />
+    <addaction name="actionHelpPlugins" />
+    <addaction name="separator" />
+    <addaction name="actionHelpAbout" />
+    <addaction name="actionHelpAbout_Qt" />
+   </widget>
+   <addaction name="menuFile" />
+   <addaction name="menuEdit" />
+   <addaction name="menuView" />
+   <addaction name="menuWindow" />
+   <addaction name="menuHelp" />
+  </widget>
+  <action name="actionFileNew" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/new.png</normaloff>:/new/prefix1/Resources/new.png</iconset>
+   </property>
+   <property name="text" >
+    <string>&amp;New Project</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+N</string>
+   </property>
+  </action>
+  <action name="actionFileOpen" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/open.png</normaloff>:/new/prefix1/Resources/open.png</iconset>
+   </property>
+   <property name="text" >
+    <string>&amp;Open Project...</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionFileSave" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/save.png</normaloff>:/new/prefix1/Resources/save.png</iconset>
+   </property>
+   <property name="text" >
+    <string>&amp;Save Project</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+S</string>
+   </property>
+  </action>
+  <action name="actionFileSaveAs" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/saveAs.png</normaloff>:/new/prefix1/Resources/saveAs.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Save Project &amp;As...</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+A</string>
+   </property>
+  </action>
+  <action name="actionFileSyncClients" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/sync.png</normaloff>:/new/prefix1/Resources/sync.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Sync Clients</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+Y</string>
+   </property>
+  </action>
+  <action name="actionFileExit" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/exit.png</normaloff>:/new/prefix1/Resources/exit.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Exit</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+Q</string>
+   </property>
+  </action>
+  <action name="actionFileExitAll" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/exitAll.png</normaloff>:/new/prefix1/Resources/exitAll.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Exit All</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+W</string>
+   </property>
+  </action>
+  <action name="actionEditDesignDistortionMap" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/distortionMode.png</normaloff>:/new/prefix1/Resources/distortionMode.png</iconset>
+   </property>
+   <property name="text" >
+    <string>&amp;Distortion Map</string>
+   </property>
+   <property name="shortcut" >
+    <string>Alt+D</string>
+   </property>
+   <property name="shortcutContext" >
+    <enum>Qt::ApplicationShortcut</enum>
+   </property>
+  </action>
+  <action name="actionEditDesignBlendMap" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/blendMode.png</normaloff>:/new/prefix1/Resources/blendMode.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Blend Map</string>
+   </property>
+   <property name="shortcut" >
+    <string>Alt+B</string>
+   </property>
+   <property name="shortcutContext" >
+    <enum>Qt::ApplicationShortcut</enum>
+   </property>
+  </action>
+  <action name="actionEditPreference" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/settings.png</normaloff>:/new/prefix1/Resources/settings.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Preferences</string>
+   </property>
+   <property name="iconText" >
+    <string>Preferences</string>
+   </property>
+   <property name="toolTip" >
+    <string>Preferences</string>
+   </property>
+   <property name="statusTip" >
+    <string>Opens the preferences dialog</string>
+   </property>
+   <property name="shortcut" >
+    <string>Alt+P</string>
+   </property>
+   <property name="shortcutContext" >
+    <enum>Qt::ApplicationShortcut</enum>
+   </property>
+  </action>
+  <action name="actionViewPerspective" >
+   <property name="text" >
+    <string>&amp;Perspective</string>
+   </property>
+  </action>
+  <action name="actionViewCenter" >
+   <property name="text" >
+    <string>&amp;Center</string>
+   </property>
+  </action>
+  <action name="actionViewTop" >
+   <property name="text" >
+    <string>Top</string>
+   </property>
+  </action>
+  <action name="actionViewSide" >
+   <property name="text" >
+    <string>Side</string>
+   </property>
+  </action>
+  <action name="actionViewFront" >
+   <property name="text" >
+    <string>Front</string>
+   </property>
+  </action>
+  <action name="actionViewAxis" >
+   <property name="text" >
+    <string>&amp;Axis</string>
+   </property>
+  </action>
+  <action name="actionViewGrid" >
+   <property name="text" >
+    <string>&amp;Grid</string>
+   </property>
+  </action>
+  <action name="actionViewInfo" >
+   <property name="text" >
+    <string>&amp;Info</string>
+   </property>
+  </action>
+  <action name="actionViewViewAll" >
+   <property name="text" >
+    <string>View All</string>
+   </property>
+  </action>
+  <action name="actionWindowSceneViewer" >
+   <property name="text" >
+    <string>Scene Viewer</string>
+   </property>
+  </action>
+  <action name="actionWindowSceneDialog" >
+   <property name="text" >
+    <string>Scene</string>
+   </property>
+  </action>
+  <action name="actionWindowScreenDialog" >
+   <property name="text" >
+    <string>Screen</string>
+   </property>
+  </action>
+  <action name="actionWindowChannelManager" >
+   <property name="text" >
+    <string>Channels</string>
+   </property>
+  </action>
+  <action name="actionHelpHelp" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/help.png</normaloff>:/new/prefix1/Resources/help.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Help...</string>
+   </property>
+   <property name="shortcut" >
+    <string>F1</string>
+   </property>
+  </action>
+  <action name="actionHelpAbout" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/projDesigner.png</normaloff>:/new/prefix1/Resources/projDesigner.png</iconset>
+   </property>
+   <property name="text" >
+    <string>About Projection Designer</string>
+   </property>
+  </action>
+  <action name="actionFileExportDataset" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/export.png</normaloff>:/new/prefix1/Resources/export.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Export Data set</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+E</string>
+   </property>
+  </action>
+  <action name="actionHelpPlugins" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/plugins.png</normaloff>:/new/prefix1/Resources/plugins.png</iconset>
+   </property>
+   <property name="text" >
+    <string>Plugins...</string>
+   </property>
+   <property name="shortcut" >
+    <string>Ctrl+Alt+P</string>
+   </property>
+  </action>
+  <action name="actionHelpAbout_Qt" >
+   <property name="icon" >
+    <iconset resource="../../projdesigner.qrc" >
+     <normaloff>:/new/prefix1/Resources/aboutQt.png</normaloff>:/new/prefix1/Resources/aboutQt.png</iconset>
+   </property>
+   <property name="text" >
+    <string>About Qt</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QPanelWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QPanelWidget.h</header>
+  </customwidget>
+  <customwidget>
+   <class>projection::QDesignViewWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QDesignViewWidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="../../projdesigner.qrc" />
+ </resources>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qpanelwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qpanelwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qpanelwidget.ui	(revision 4)
@@ -0,0 +1,206 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QPanelWidget</class>
+ <widget class="QWidget" name="QPanelWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>196</width>
+    <height>722</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Designer</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QTabWidget" name="tabWidget" >
+     <widget class="QWidget" name="channelsTab" >
+      <attribute name="title" >
+       <string>Channels</string>
+      </attribute>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>4</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="projection::QChannelManagerWidget" name="channelManager" >
+           <property name="maximumSize" >
+            <size>
+             <width>16777215</width>
+             <height>160</height>
+            </size>
+           </property>
+           <property name="focusPolicy" >
+            <enum>Qt::StrongFocus</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="channelGroup" >
+           <property name="sizePolicy" >
+            <sizepolicy>
+             <hsizetype>5</hsizetype>
+             <vsizetype>5</vsizetype>
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="title" >
+            <string>Channel</string>
+           </property>
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>4</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="projection::QChannelWidget" name="channel" >
+              <property name="focusPolicy" >
+               <enum>Qt::StrongFocus</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" >
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="screenTab" >
+      <attribute name="title" >
+       <string>Screen</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="projection::QScreenWidget" name="screen" />
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="sceneTab" >
+      <attribute name="title" >
+       <string>Scene</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="projection::QSceneWidget" name="scene" />
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QChannelManagerWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QChannelManagerWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QScreenWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QScreenWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QChannelWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QChannelWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QSceneWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QSceneWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>channelManager</tabstop>
+  <tabstop>channel</tabstop>
+  <tabstop>tabWidget</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qpreferencedialog.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qpreferencedialog.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qpreferencedialog.ui	(revision 4)
@@ -0,0 +1,563 @@
+<ui version="4.0" >
+ <class>QPreferenceDialog</class>
+ <widget class="QDialog" name="QPreferenceDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>345</width>
+    <height>357</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Preference</string>
+  </property>
+  <property name="windowIcon" >
+   <iconset resource="../../projdesigner.qrc" >
+    <normaloff>:/new/prefix1/Resources/settings.png</normaloff>:/new/prefix1/Resources/settings.png</iconset>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <property name="margin" >
+    <number>4</number>
+   </property>
+   <item>
+    <layout class="QVBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QGroupBox" name="gridGroupBox" >
+       <property name="title" >
+        <string>Grid</string>
+       </property>
+       <layout class="QHBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="gridSizeLabel" >
+            <property name="text" >
+             <string>Size</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="gridSizeEdit" >
+            <property name="minimumSize" >
+             <size>
+              <width>64</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="maximumSize" >
+             <size>
+              <width>64</width>
+              <height>16777215</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="gridSubdivLabel" >
+            <property name="text" >
+             <string>Subdivision</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSpinBox" name="gridSubdivSpinBox" />
+          </item>
+          <item>
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="offscreenSceneRenderingGroupBox" >
+       <property name="title" >
+        <string>Off-screen Scene Rendering</string>
+       </property>
+       <layout class="QHBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="bufferSizeLabel" >
+              <property name="text" >
+               <string>Buffer size</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="bufferWidthComboBox" >
+              <item>
+               <property name="text" >
+                <string>128</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>256</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>512</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>1024</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>2048</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>4096</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="bufferHeightComboBox" >
+              <item>
+               <property name="text" >
+                <string>128</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>256</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>512</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>1024</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>2048</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>4096</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="blendMapGroupBox" >
+       <property name="title" >
+        <string>Blend Map</string>
+       </property>
+       <layout class="QHBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QCheckBox" name="softEdgeCheckBox" >
+              <property name="text" >
+               <string>Soft edge</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="blendEdgeWidthLabel" >
+              <property name="sizePolicy" >
+               <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text" >
+               <string> Width</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="blendEdgeWidthSpinBox" />
+            </item>
+            <item>
+             <widget class="QLabel" name="blendEdgeExponentLabel" >
+              <property name="text" >
+               <string>Exponent</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="blendEdgeExponentEdit" >
+              <property name="maximumSize" >
+               <size>
+                <width>32</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
+               <size>
+                <width>20</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="exportGroupBox" >
+       <property name="title" >
+        <string>Export</string>
+       </property>
+       <layout class="QHBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="exportSizeLabel" >
+              <property name="text" >
+               <string>Image size</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="exportWidthComboBox" >
+              <property name="editable" >
+               <bool>true</bool>
+              </property>
+              <item>
+               <property name="text" >
+                <string>256</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>512</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>1024</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>2048</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="exportHeightComboBox" >
+              <property name="editable" >
+               <bool>true</bool>
+              </property>
+              <item>
+               <property name="text" >
+                <string>256</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>512</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>1024</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>2048</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QLabel" name="exportFileNamePatternLabel" >
+            <property name="text" >
+             <string>Export file name pattern</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType" >
+               <enum>QSizePolicy::Fixed</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
+               <size>
+                <width>10</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item>
+             <layout class="QGridLayout" >
+              <property name="margin" >
+               <number>0</number>
+              </property>
+              <property name="spacing" >
+               <number>6</number>
+              </property>
+              <item row="0" column="0" >
+               <widget class="QLabel" name="exportDistortMapPatternLabel" >
+                <property name="text" >
+                 <string>Distortion map file</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0" >
+               <widget class="QLabel" name="exportViewMatrixPatternLabel" >
+                <property name="text" >
+                 <string>View matrix file</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1" >
+               <widget class="QLineEdit" name="exportDistortMapPatternEdit" >
+                <property name="minimumSize" >
+                 <size>
+                  <width>180</width>
+                  <height>0</height>
+                 </size>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="1" >
+               <widget class="QLineEdit" name="exportViewMatrixPatternEdit" />
+              </item>
+              <item row="1" column="1" >
+               <widget class="QLineEdit" name="exportBlendMapPatternEdit" />
+              </item>
+              <item row="1" column="0" >
+               <widget class="QLabel" name="exportBlendMapPatternLabel" >
+                <property name="text" >
+                 <string>Blend map file</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0" >
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0" >
+        <size>
+         <width>325</width>
+         <height>71</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pB_ClosePrefDiag" >
+       <property name="text" >
+        <string>Close</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../projdesigner.qrc" />
+ </resources>
+ <connections>
+  <connection>
+   <sender>pB_ClosePrefDiag</sender>
+   <signal>clicked()</signal>
+   <receiver>QPreferenceDialog</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>172</x>
+     <y>345</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>172</x>
+     <y>181</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qprojectionmatrixwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qprojectionmatrixwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qprojectionmatrixwidget.ui	(revision 4)
@@ -0,0 +1,158 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QProjectionMatrixWidget</class>
+ <widget class="QWidget" name="QProjectionMatrixWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>169</width>
+    <height>110</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Projection</string>
+     </property>
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="fovLabel" >
+            <property name="text" >
+             <string>FOV</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="fovEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="aspectLabel" >
+            <property name="text" >
+             <string>Aspect</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="aspectRatioEdit" />
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="nearLabel" >
+            <property name="text" >
+             <string>Near</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="nearEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="farLabel" >
+            <property name="text" >
+             <string>Far</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="farEdit" />
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="offaxisLabel" >
+            <property name="text" >
+             <string>Off-axis </string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="offaxisXLabel" >
+            <property name="text" >
+             <string>X</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="offaxisXEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="offaxisYLabel" >
+            <property name="text" >
+             <string>Y</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="offaxisYEdit" />
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+  <tabstop>fovEdit</tabstop>
+  <tabstop>aspectRatioEdit</tabstop>
+  <tabstop>nearEdit</tabstop>
+  <tabstop>farEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qscenewidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qscenewidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qscenewidget.ui	(revision 4)
@@ -0,0 +1,265 @@
+<ui version="4.0" >
+ <class>QSceneWidget</class>
+ <widget class="QWidget" name="QSceneWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>178</width>
+    <height>242</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Scene Settings</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>4</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <layout class="QVBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="projection::QTransformMatrixWidget" native="1" name="transformWidget" >
+       <property name="focusPolicy" >
+        <enum>Qt::StrongFocus</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="contentGroup" >
+       <property name="title" >
+        <string>Content</string>
+       </property>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="typeLabel" >
+              <property name="text" >
+               <string>Type</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="typeComboBox" >
+              <property name="minimumSize" >
+               <size>
+                <width>96</width>
+                <height>0</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" >
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QStackedWidget" name="stackedWidget" >
+            <property name="focusPolicy" >
+             <enum>Qt::StrongFocus</enum>
+            </property>
+            <property name="currentIndex" >
+             <number>-1</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="showInDesignViewCheckBox" >
+       <property name="text" >
+        <string>Show in Design View</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="sceneSizeLabel" >
+         <property name="text" >
+          <string>Scene size</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLineEdit" name="sceneSizeEdit" >
+         <property name="maximumSize" >
+          <size>
+           <width>64</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QCheckBox" name="gridCheckBox" >
+         <property name="text" >
+          <string>Grid</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="gridSizeLabel" >
+         <property name="text" >
+          <string>Size</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLineEdit" name="gridSizeEdit" >
+         <property name="maximumSize" >
+          <size>
+           <width>64</width>
+           <height>16777215</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="centerViewButton" >
+         <property name="text" >
+          <string>Center View</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="viewAllButton" >
+         <property name="text" >
+          <string>ViewAll</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QTransformMatrixWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QTransformMatrixWidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>typeComboBox</tabstop>
+  <tabstop>stackedWidget</tabstop>
+  <tabstop>showInDesignViewCheckBox</tabstop>
+  <tabstop>gridCheckBox</tabstop>
+  <tabstop>gridSizeEdit</tabstop>
+  <tabstop>centerViewButton</tabstop>
+  <tabstop>viewAllButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qscreenwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qscreenwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qscreenwidget.ui	(revision 4)
@@ -0,0 +1,631 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QScreenWidget</class>
+ <widget class="QWidget" name="QScreenWidget" >
+  <property name="geometry" >
+   <rect>
+	<x>0</x>
+	<y>0</y>
+	<width>183</width>
+	<height>222</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Screen Settings</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+	<number>4</number>
+   </property>
+   <property name="spacing" >
+	<number>6</number>
+   </property>
+   <item>
+	<layout class="QVBoxLayout" >
+	 <property name="margin" >
+	  <number>0</number>
+	 </property>
+	 <property name="spacing" >
+	  <number>6</number>
+	 </property>
+	 <item>
+	  <widget class="projection::QTransformMatrixWidget" name="transformWidget" >
+	   <property name="focusPolicy" >
+		<enum>Qt::StrongFocus</enum>
+	   </property>
+	  </widget>
+	 </item>
+	 <item>
+	  <widget class="QGroupBox" name="shapeGroup" >
+	   <property name="title" >
+		<string>Shape</string>
+	   </property>
+	   <layout class="QHBoxLayout" >
+		<property name="margin" >
+		 <number>4</number>
+		</property>
+		<property name="spacing" >
+		 <number>6</number>
+		</property>
+		<item>
+		 <layout class="QVBoxLayout" >
+		  <property name="margin" >
+		   <number>0</number>
+		  </property>
+		  <property name="spacing" >
+		   <number>6</number>
+		  </property>
+		  <item>
+		   <layout class="QHBoxLayout" >
+			<property name="margin" >
+			 <number>0</number>
+			</property>
+			<property name="spacing" >
+			 <number>6</number>
+			</property>
+			<item>
+			 <widget class="QLabel" name="typeLabel" >
+			  <property name="text" >
+			   <string>Type</string>
+			  </property>
+			 </widget>
+			</item>
+			<item>
+			 <widget class="QComboBox" name="typeComboBox" >
+			  <property name="minimumSize" >
+			   <size>
+				<width>96</width>
+				<height>0</height>
+			   </size>
+			  </property>
+			  <item>
+			   <property name="text" >
+				<string>Dome</string>
+			   </property>
+			  </item>
+			  <item>
+			   <property name="text" >
+				<string>Plane</string>
+			   </property>
+			  </item>
+			  <item>
+			   <property name="text" >
+				<string>Box</string>
+			   </property>
+			  </item>
+			 </widget>
+			</item>
+			<item>
+			 <spacer>
+			  <property name="orientation" >
+			   <enum>Qt::Horizontal</enum>
+			  </property>
+			  <property name="sizeHint" >
+			   <size>
+				<width>40</width>
+				<height>20</height>
+			   </size>
+			  </property>
+			 </spacer>
+			</item>
+		   </layout>
+		  </item>
+		  <item>
+		   <widget class="QStackedWidget" name="stackedWidget" >
+			<property name="currentIndex" >
+			 <number>0</number>
+			</property>
+			<widget class="QWidget" name="domePage" >
+			 <layout class="QHBoxLayout" >
+			  <property name="margin" >
+			   <number>4</number>
+			  </property>
+			  <property name="spacing" >
+			   <number>6</number>
+			  </property>
+			  <item>
+			   <layout class="QVBoxLayout" >
+				<property name="margin" >
+				 <number>0</number>
+				</property>
+				<property name="spacing" >
+				 <number>6</number>
+				</property>
+				<item>
+				 <layout class="QHBoxLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item>
+				   <widget class="QLabel" name="domeRadiusLabel" >
+					<property name="text" >
+					 <string>Radius</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item>
+				   <widget class="QLineEdit" name="domeRadiusEdit" />
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <layout class="QHBoxLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item>
+				   <widget class="QLabel" name="domeAzimResLabel" >
+					<property name="text" >
+					 <string>Azimuth Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item>
+				   <widget class="QSpinBox" name="domeAzimResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>2</number>
+					</property>
+				   </widget>
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <layout class="QHBoxLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item>
+				   <widget class="QLabel" name="domeElevResLabel" >
+					<property name="text" >
+					 <string>Elevation Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item>
+				   <widget class="QSpinBox" name="domeElevResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>2</number>
+					</property>
+				   </widget>
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <layout class="QHBoxLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item>
+				   <widget class="QLabel" name="domeSubdivLabel" >
+					<property name="text" >
+					 <string>Subdivision</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item>
+				   <widget class="QSpinBox" name="domeSubdivSpinBox" >
+					<property name="maximum" >
+					 <number>8</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <widget class="QCheckBox" name="domeFullDomeCheckBox" >
+				  <property name="text" >
+				   <string>Full dome</string>
+				  </property>
+				 </widget>
+				</item>
+				<item>
+				 <spacer>
+				  <property name="orientation" >
+				   <enum>Qt::Vertical</enum>
+				  </property>
+				  <property name="sizeHint" >
+				   <size>
+					<width>20</width>
+					<height>40</height>
+				   </size>
+				  </property>
+				 </spacer>
+				</item>
+			   </layout>
+			  </item>
+			 </layout>
+			</widget>
+			<widget class="QWidget" name="planePage" >
+			 <layout class="QHBoxLayout" >
+			  <property name="margin" >
+			   <number>4</number>
+			  </property>
+			  <property name="spacing" >
+			   <number>6</number>
+			  </property>
+			  <item>
+			   <layout class="QVBoxLayout" >
+				<property name="margin" >
+				 <number>0</number>
+				</property>
+				<property name="spacing" >
+				 <number>6</number>
+				</property>
+				<item>
+				 <layout class="QGridLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item row="1" column="0" >
+				   <widget class="QLabel" name="planeHeightLabel" >
+					<property name="text" >
+					 <string>Height</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="2" >
+				   <widget class="QLabel" name="planeHorResLabel" >
+					<property name="text" >
+					 <string>Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="3" >
+				   <widget class="QSpinBox" name="planeHorResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="1" column="2" >
+				   <widget class="QLabel" name="planeVertResLabel" >
+					<property name="text" >
+					 <string>Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="1" >
+				   <widget class="QLineEdit" name="planeWidthEdit" />
+				  </item>
+				  <item row="0" column="0" >
+				   <widget class="QLabel" name="planeWidthLabel" >
+					<property name="text" >
+					 <string>Width</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="1" column="1" >
+				   <widget class="QLineEdit" name="planeHeightEdit" />
+				  </item>
+				  <item row="1" column="3" >
+				   <widget class="QSpinBox" name="planeVertResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <spacer>
+				  <property name="orientation" >
+				   <enum>Qt::Vertical</enum>
+				  </property>
+				  <property name="sizeHint" >
+				   <size>
+					<width>20</width>
+					<height>40</height>
+				   </size>
+				  </property>
+				 </spacer>
+				</item>
+			   </layout>
+			  </item>
+			 </layout>
+			</widget>
+			<widget class="QWidget" name="boxPage" >
+			 <layout class="QHBoxLayout" >
+			  <property name="margin" >
+			   <number>4</number>
+			  </property>
+			  <property name="spacing" >
+			   <number>6</number>
+			  </property>
+			  <item>
+			   <layout class="QVBoxLayout" >
+				<property name="margin" >
+				 <number>0</number>
+				</property>
+				<property name="spacing" >
+				 <number>6</number>
+				</property>
+				<item>
+				 <layout class="QGridLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item row="1" column="3" >
+				   <widget class="QSpinBox" name="boxVertResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="2" >
+				   <widget class="QLabel" name="boxHorResLabel" >
+					<property name="text" >
+					 <string>Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="2" column="2" >
+				   <widget class="QLabel" name="boxDepthResLabel" >
+					<property name="text" >
+					 <string>Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="1" column="0" >
+				   <widget class="QLabel" name="boxHeightLabel" >
+					<property name="text" >
+					 <string>Height</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="0" >
+				   <widget class="QLabel" name="boxWidthLabel" >
+					<property name="text" >
+					 <string>Width</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="0" column="1" >
+				   <widget class="QLineEdit" name="boxWidthEdit" />
+				  </item>
+				  <item row="0" column="3" >
+				   <widget class="QSpinBox" name="boxHorResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="2" column="3" >
+				   <widget class="QSpinBox" name="boxDepthResSpinBox" >
+					<property name="maximum" >
+					 <number>128</number>
+					</property>
+					<property name="minimum" >
+					 <number>1</number>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="1" column="2" >
+				   <widget class="QLabel" name="boxVertResLabel" >
+					<property name="text" >
+					 <string>Res.</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="2" column="1" >
+				   <widget class="QLineEdit" name="boxDepthEdit" />
+				  </item>
+				  <item row="2" column="0" >
+				   <widget class="QLabel" name="boxDepthLabel" >
+					<property name="text" >
+					 <string>Depth</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item row="1" column="1" >
+				   <widget class="QLineEdit" name="boxHeightEdit" />
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <spacer>
+				  <property name="orientation" >
+				   <enum>Qt::Vertical</enum>
+				  </property>
+				  <property name="sizeHint" >
+				   <size>
+					<width>20</width>
+					<height>40</height>
+				   </size>
+				  </property>
+				 </spacer>
+				</item>
+			   </layout>
+			  </item>
+			 </layout>
+			</widget>
+			<widget class="QWidget" name="modelPage" >
+			 <layout class="QHBoxLayout" >
+			  <property name="margin" >
+			   <number>4</number>
+			  </property>
+			  <property name="spacing" >
+			   <number>6</number>
+			  </property>
+			  <item>
+			   <layout class="QVBoxLayout" >
+				<property name="margin" >
+				 <number>0</number>
+				</property>
+				<property name="spacing" >
+				 <number>6</number>
+				</property>
+				<item>
+				 <layout class="QHBoxLayout" >
+				  <property name="margin" >
+				   <number>0</number>
+				  </property>
+				  <property name="spacing" >
+				   <number>6</number>
+				  </property>
+				  <item>
+				   <widget class="QLabel" name="modelFileNameLabel" >
+					<property name="text" >
+					 <string>File</string>
+					</property>
+				   </widget>
+				  </item>
+				  <item>
+				   <widget class="QLineEdit" name="modelFileNameEdit" />
+				  </item>
+				  <item>
+				   <widget class="QPushButton" name="modelBrowseButton" >
+					<property name="sizePolicy" >
+					 <sizepolicy>
+					  <hsizetype>0</hsizetype>
+					  <vsizetype>0</vsizetype>
+					  <horstretch>0</horstretch>
+					  <verstretch>0</verstretch>
+					 </sizepolicy>
+					</property>
+					<property name="maximumSize" >
+					 <size>
+					  <width>23</width>
+					  <height>16777215</height>
+					 </size>
+					</property>
+					<property name="text" >
+					 <string>...</string>
+					</property>
+				   </widget>
+				  </item>
+				 </layout>
+				</item>
+				<item>
+				 <spacer>
+				  <property name="orientation" >
+				   <enum>Qt::Vertical</enum>
+				  </property>
+				  <property name="sizeHint" >
+				   <size>
+					<width>20</width>
+					<height>40</height>
+				   </size>
+				  </property>
+				 </spacer>
+				</item>
+			   </layout>
+			  </item>
+			 </layout>
+			</widget>
+		   </widget>
+		  </item>
+		 </layout>
+		</item>
+	   </layout>
+	  </widget>
+	 </item>
+	 <item>
+	  <layout class="QHBoxLayout" >
+	   <property name="margin" >
+		<number>0</number>
+	   </property>
+	   <property name="spacing" >
+		<number>6</number>
+	   </property>
+	   <item>
+		<widget class="QCheckBox" name="frameCheckBox" >
+		 <property name="text" >
+		  <string>Wireframe</string>
+		 </property>
+		</widget>
+	   </item>
+	   <item>
+		<widget class="QLabel" name="frameLineWidthLabel" >
+		 <property name="text" >
+		  <string>Width</string>
+		 </property>
+		</widget>
+	   </item>
+	   <item>
+		<widget class="QSpinBox" name="frameLineWidthSpinBox" >
+		 <property name="maximum" >
+		  <number>4</number>
+		 </property>
+		 <property name="minimum" >
+		  <number>1</number>
+		 </property>
+		</widget>
+	   </item>
+	  </layout>
+	 </item>
+	</layout>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QTransformMatrixWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QTransformMatrixWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>typeComboBox</tabstop>
+  <tabstop>transformWidget</tabstop>
+  <tabstop>domeRadiusEdit</tabstop>
+  <tabstop>domeAzimResSpinBox</tabstop>
+  <tabstop>domeElevResSpinBox</tabstop>
+  <tabstop>domeFullDomeCheckBox</tabstop>
+  <tabstop>planeWidthEdit</tabstop>
+  <tabstop>planeHeightEdit</tabstop>
+  <tabstop>planeHorResSpinBox</tabstop>
+  <tabstop>planeVertResSpinBox</tabstop>
+  <tabstop>boxWidthEdit</tabstop>
+  <tabstop>boxHeightEdit</tabstop>
+  <tabstop>boxDepthEdit</tabstop>
+  <tabstop>boxHorResSpinBox</tabstop>
+  <tabstop>boxVertResSpinBox</tabstop>
+  <tabstop>boxDepthResSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qsetupdialog.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qsetupdialog.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qsetupdialog.ui	(revision 4)
@@ -0,0 +1,206 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QSetupDialog</class>
+ <widget class="QWidget" name="QSetupDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>196</width>
+    <height>356</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Multichannel Projection Designer</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QTabWidget" name="tabWidget" >
+     <widget class="QWidget" name="channelsTab" >
+      <attribute name="title" >
+       <string>Channels</string>
+      </attribute>
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>4</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="projection::QChannelManagerWidget" name="channelManager" >
+           <property name="maximumSize" >
+            <size>
+             <width>16777215</width>
+             <height>120</height>
+            </size>
+           </property>
+           <property name="focusPolicy" >
+            <enum>Qt::StrongFocus</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="channelGroup" >
+           <property name="sizePolicy" >
+            <sizepolicy>
+             <hsizetype>5</hsizetype>
+             <vsizetype>5</vsizetype>
+             <horstretch>0</horstretch>
+             <verstretch>1</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="title" >
+            <string>Channel</string>
+           </property>
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>4</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="projection::QChannelWidget" name="channel" >
+              <property name="focusPolicy" >
+               <enum>Qt::StrongFocus</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" >
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="screenTab" >
+      <attribute name="title" >
+       <string>Screen</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="projection::QScreenWidget" name="screen" />
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="sceneTab" >
+      <attribute name="title" >
+       <string>Scene</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="projection::QSceneWidget" name="scene" />
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <customwidgets>
+  <customwidget>
+   <class>projection::QChannelManagerWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QChannelManagerWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QScreenWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QScreenWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QChannelWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QChannelWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+  <customwidget>
+   <class>projection::QSceneWidget</class>
+   <extends>QWidget</extends>
+   <header>gui/QSceneWidget.h</header>
+   <container>0</container>
+   <pixmap></pixmap>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>channelManager</tabstop>
+  <tabstop>channel</tabstop>
+  <tabstop>tabWidget</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/gui/qtransformmatrixwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesigner/include/gui/qtransformmatrixwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/gui/qtransformmatrixwidget.ui	(revision 4)
@@ -0,0 +1,111 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>QTransformMatrixWidget</class>
+ <widget class="QWidget" name="QTransformMatrixWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>179</width>
+    <height>78</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Matrix Settings</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QGroupBox" name="transformGroup" >
+     <property name="title" >
+      <string>Transform</string>
+     </property>
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QGridLayout" >
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item row="0" column="3" >
+         <widget class="QLineEdit" name="posZEdit" />
+        </item>
+        <item row="1" column="1" >
+         <widget class="QLineEdit" name="rotHEdit" />
+        </item>
+        <item row="0" column="0" >
+         <widget class="QLabel" name="posLabel" >
+          <property name="text" >
+           <string>Pos</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0" >
+         <widget class="QLabel" name="rotLabel" >
+          <property name="text" >
+           <string>Rot</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1" >
+         <widget class="QLineEdit" name="posXEdit" />
+        </item>
+        <item row="1" column="3" >
+         <widget class="QLineEdit" name="rotREdit" />
+        </item>
+        <item row="1" column="2" >
+         <widget class="QLineEdit" name="rotPEdit" />
+        </item>
+        <item row="0" column="2" >
+         <widget class="QLineEdit" name="posYEdit" />
+        </item>
+        <item row="2" column="0" >
+         <widget class="QLabel" name="scaleLabel" >
+          <property name="text" >
+           <string>Scale</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1" >
+         <widget class="QLineEdit" name="scaleXEdit" />
+        </item>
+        <item row="2" column="2" >
+         <widget class="QLineEdit" name="scaleYEdit" />
+        </item>
+        <item row="2" column="3" >
+         <widget class="QLineEdit" name="scaleZEdit" />
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+  <tabstop>posXEdit</tabstop>
+  <tabstop>posYEdit</tabstop>
+  <tabstop>posZEdit</tabstop>
+  <tabstop>rotHEdit</tabstop>
+  <tabstop>rotPEdit</tabstop>
+  <tabstop>rotREdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesigner/include/interfaces.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/interfaces.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/interfaces.h	(revision 4)
@@ -0,0 +1,708 @@
+#ifndef INTERFACES_H
+#define INTERFACES_H
+
+#include <QtGui>
+#include <QWidget>
+#include <QtXml>
+//#include <QGLViewer/frame.h>
+
+class ProjectorWidget;
+class ProjectorData;
+
+/**
+ * Projector plugin interface class to have common interface with all projector plugins.
+ *
+ */
+class ProjectorInterface
+{
+
+public:
+
+
+    /**
+     * Destructor (virtual because the class is pure virtual).
+     *
+     */
+    virtual ~ProjectorInterface() {}
+
+
+    /**
+     * Gets the name of the plugin.
+     *
+     * @return The name of the plugin.
+     *
+     */
+    virtual QString name(void) const = 0;
+
+
+    /**
+     * Gets the list of the available projectors.
+     *
+     * @return The list of the available projectors.
+     *
+     */
+    virtual QStringList projectors(void) const = 0;
+
+
+    /**
+     * Instanciates a new ProjectorWidget for the specified projector.
+     * This function is called by the QChannelWidget constructor, when the 
+     * stackedWidget is built. 
+     *
+     * @param projector A const reference on a string that contains the name of
+     *                  the projector, such as projectors() has returned it.
+     *
+     * @return A pointer on the new instanciated ProjectorWidget.
+     *
+     */
+    virtual ProjectorWidget *newProjectorWidget(const QString& projector) = 0;
+
+
+    /**
+     * Instanciates a new ProjectorData for the specified projector.
+     * This function is called by the Channel when it needs to create or copy 
+     * some ProjectorData.
+     *
+     * @param projector A const reference on a string that contains the name of
+     *                  the projector, such as projectors() has returned it.
+     *
+     * @return A pointer on the new instanciated ProjectorData.
+     *
+     */
+    virtual ProjectorData *newProjectorData(const QString& projector) = 0;
+
+};
+
+
+/**
+ * Projector data class to store informations about Projectors.
+ * This class is not a pure virtual class, so projector plugins does not need to
+ * instanciate it if it is not necessary.
+ *
+ */
+class ProjectorData
+{
+
+public:
+
+
+    /**
+     * Constructor.
+     *
+     * @param plugin A pointer on the plugin that owns the projector.
+     *
+     */
+    ProjectorData(ProjectorInterface *plugin):
+	m_bShow(true),
+	m_bShowArea(true),
+	m_plugin(plugin)
+	{
+	    Q_ASSERT(NULL!=plugin);
+	}
+
+
+    /**
+     * Copy constructor.
+     *
+     * @param data A const reference on the source data.
+     *
+     */
+    ProjectorData (const ProjectorData& data)
+	{
+	    copy_from(data);
+	}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    virtual ~ProjectorData() {}
+
+
+    /**
+     * Gets the ProjectorInterface which instanciated the ProjectorData.
+     *
+     * @return A pointer on the ProjectorInterface which instanciated the
+     *         ProjectorData.
+     *
+     */
+    ProjectorInterface* plugin() {return m_plugin;}
+
+
+    /**
+     * Gets the ProjectorInterface which instanciated the ProjectorData.
+     * This fonction differs from the previous one by the "const" attribute.
+     *
+     * @return A const pointer on the ProjectorInterface which instanciated the
+     *         ProjectorData.
+     *
+     */
+    const ProjectorInterface* plugin() const {return m_plugin;}
+
+
+    /**
+     * Draws the projector.
+     * This method draws the geometric projector data. For instance, for a 
+     * standard projector, it draws the frustum in the scene.
+     *
+     * @param bSelected true if the projector is selected.
+     *
+     */
+    virtual void draw(bool bSelected) {Q_UNUSED(bSelected);}
+
+
+    /**
+     * Starts the rendering through the projector.
+     * For a standard projector, this is the call to 'glFrustum()'.
+     *
+     */
+    virtual void beginDraw(void){}
+
+
+    /**
+     * Ends the rendering through the projector.
+     * For a standard projector, this is the call to 'glPop...()'.
+     * This method restores the state of OpenGL before the call to beginDraw().
+     *
+     */
+    virtual void endDraw(void){}
+
+
+    /**
+     * Starts the projection of the image.
+     * This is used by Screen::draw(source) when source is 
+     * PROJECT_SOURCE_PROJECTORAREA or PROJECT_SOURCE_EXPORT_BLENDING
+     *
+     */
+    virtual void beginProjection(void){}
+
+
+    /**
+     * Ends the projection of the image.
+     * This is used by Screen::draw(source) when source is 
+     * PROJECT_SOURCE_PROJECTORAREA or PROJECT_SOURCE_EXPORT_BLENDING
+     *
+     */
+    virtual void endProjection(void){}
+
+
+    /**
+     * Sets the VisibleFar distance parameter.
+     *
+     * The Visible Far dist is used for the representation of the projector from
+     * outside. The name comes from the frustum case, but it is used for any
+     * kind of projector now.
+     *
+     * @param farDist The new visible-far distance.
+     *
+     */
+    virtual void setVisibleFar(float farDist) {Q_UNUSED(farDist);}
+
+
+    /**
+     * Copies the data from a ProjectorData.
+     *
+     * @param data A const-reference on the data to be copied.
+     *
+     * @return true if the copy suceeds, false otherwise.
+     *
+     */
+    virtual bool copy_from(const ProjectorData& data) {Q_ASSERT(m_plugin==data.m_plugin); m_bShow=data.m_bShow; m_bShowArea=data.m_bShowArea; return true;}
+
+
+    /**
+     * Check if 2 datas are equal.
+     *
+     * @param data A const-reference on the data to be checked.
+     * @return true if the datas are the same, false otherwise.
+     *
+     */
+    virtual bool is_equal_to(const ProjectorData& data) const {return m_plugin==data.m_plugin && m_bShow==data.m_bShow && m_bShowArea==data.m_bShowArea;}
+
+
+    /**
+     * Sets the Show parameter.
+     *
+     * @param bShow The new Show parameter.
+     *
+     */
+    void setShow(bool bShow) {m_bShow = bShow;}
+
+
+    /**
+     * Gets the Show parameter.
+     *
+     * @return The Show parameter.
+     *
+     */
+    bool getShow() const {return m_bShow;}
+
+
+    /**
+     * Sets the ShowArea parameter.
+     *
+     * @param bShow The new ShowArea parameter.
+     *
+     */
+    void setShowArea(bool bShowArea) {m_bShowArea = bShowArea;}
+
+
+    /**
+     * Gets the ShowArea parameter.
+     *
+     * @return The ShowArea parameter.
+     *
+     */
+    bool getShowArea() const {return m_bShowArea;}
+
+
+    /**
+     * Restore the export settings from XML data.
+     *
+     * @param element Parent XML element of the export settings data.
+     *
+     */
+    virtual void initFromDOMElement(const QDomElement& element) {if (!element.isNull()) {m_bShow=element.attribute("show").toLower()=="true"; m_bShowArea=element.attribute("showArea").toLower()=="true";}}
+
+
+    /**
+     * Store the current export settings as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     *
+     * @return Current export settings data as XML data.
+     *
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const { QDomElement de = doc.createElement(name); de.setAttribute("show", (m_bShow?"true":"false")); de.setAttribute("showArea", (m_bShowArea?"true":"false")); return de;}
+
+
+    /**
+     * Gets the projector name.
+     * This is the name that is in the projector list of the
+     * ProjectorInterface::projectors().
+     *
+     * @return The name of the projector.
+     *
+     */
+    virtual const QString& projector(void) const = 0;
+
+
+    /**
+     * Gets the projector full name.
+     * This name can be used in the interface of Projection Designer to define in a unique way the projector.
+     *
+     * @return the fullname of the projector.
+     *
+     */
+    QString getFullName(void) const {
+	Q_ASSERT(m_plugin);
+	QString projector_fullname = projector();
+	projector_fullname += " (";
+	projector_fullname += m_plugin->name();
+	projector_fullname += ")";
+	return projector_fullname;
+    }
+
+protected:
+    bool m_bShow; ///< Visibility flag
+    bool m_bShowArea; ///< Area visibility flag
+
+private:
+    ProjectorInterface *m_plugin; ///< The ProjectorInterface in which the projector is.
+};
+
+
+/**
+ * Projector widget class implementation.
+ *
+ * The ProjectorWidget is used by the ChannelWidget, for the Projector part of
+ * each channel. Concerning the interface, the channel manager has a
+ * stackedWidget and a combo that are linked together. When the combo changes,
+ * the stackedWidget also changes. This defines the kind of projector to be used
+ * for the channel. The default plugin offers the frustum camera.
+ *
+ * Each widget has its own data. They can be retrieved using data().
+ *
+ */
+class ProjectorWidget: public QWidget
+{
+	Q_OBJECT
+
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    ProjectorWidget(ProjectorInterface *plugin=NULL, QWidget* pParent=0, Qt::WFlags flag=0): QWidget(pParent, flag), m_plugin(plugin) {Q_ASSERT(NULL!=plugin);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    virtual ~ProjectorWidget() {}
+
+
+    /**
+     * Gets the projector interface associated with the widget.
+     *
+     * @return The associated projector interfacec.
+     *
+     */
+    ProjectorInterface* plugin() {return m_plugin;}
+
+
+    /**
+     * Updates the GUI.
+     *
+     * This method *must* be implemented by derived classes.
+     *
+     * @param data The data used to update the GUI. The data can be NULL. In 
+     *             this case, the current data are used.
+     *
+     */
+    virtual void updateGUI(const ProjectorData* data) = 0;
+
+
+    /**
+     * Clears the widget.
+     *
+     * This can be used before disabling the widget.
+     *
+     */
+    virtual void clear(void) = 0;
+
+
+    /**
+     * Gets the data of the widget.
+     *
+     * @return The widget data.
+     *
+     */
+    virtual const ProjectorData& data(void) const = 0;
+
+
+signals:
+
+
+    /**
+     * Notify that data has changed.
+     *
+     * @param data The new data.
+     *
+     */
+    virtual void dataChanged(const ProjectorData&)=0;
+
+
+private:
+
+
+    ProjectorInterface *m_plugin; ///< The ProjectorInterface that owns the Widget.
+
+};
+
+Q_DECLARE_INTERFACE(ProjectorInterface,
+                    "jp.orihalcon.projdesigner.ProjectorInterface/1.0");
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class SceneContent;
+class SceneWidget;
+
+/**
+ * Scene Plugin Interface Implementation.
+ *
+ */
+class SceneInterface
+{
+
+public:
+
+
+    /**
+     * Destructor.
+     *
+     */
+    virtual ~SceneInterface() {}
+
+
+    /**
+     * Gets the name of the Interface.
+     *
+     * This name must be unique, to avoid conflicting plugins, just like the
+     * name of the interface is unique to avoid conflicting interfaces.
+     *
+     * @return The name of the interface.
+     *
+     */
+    virtual QString name(void) const = 0;
+
+
+    /**
+     * Gets the list of the available scenes.
+     *
+     * @return The list of the available scenes.
+     *
+     */
+    virtual QStringList scenes(void) const = 0;
+
+
+    /**
+     * Instanciates a new SceneContent for the specified scene.
+     *
+     * @param scene A const reference on a string that contains the name of the
+     *              scene, such as projectors() has returned it.
+     *
+     * @return A pointer on the new instanciated SceneContent.
+     *
+     */
+    virtual SceneContent *newSceneContent(const QString& scene) = 0;
+
+
+    /**
+     * Instanciates a new SceneWidget for the specified scene.
+     *
+     * @param scene A const reference on a string that contains the name of
+     *              the scene, such as scenes() has returned it.
+     *
+     * @return A pointer on the new instanciated SceneWidget.
+     *
+     */
+    virtual SceneWidget *newSceneWidget(const QString& scene) = 0;
+
+};
+
+/**
+ * Scene content class to store informations about Scenes.
+ * This class is not a pure virtual class, so scene plugins does not need to
+ * instanciate it if it is not necessary.
+ *
+ */
+class SceneContent
+{
+public:
+
+
+    /**
+     * Constructor.
+     *
+     * @param plugin A pointer on the plugin that owns the projector.
+     *
+     */
+    SceneContent(SceneInterface *plugin): m_plugin(plugin) {Q_ASSERT(NULL!=plugin);}
+
+
+    /**
+     * Copy constructor.
+     *
+     * @param data A const reference on the source content.
+     *
+     */
+    SceneContent (const SceneContent& content) {copy_from(content);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    virtual ~SceneContent() {}
+
+
+    /**
+     * Gets the SceneInterface which instanciated the SceneContent.
+     *
+     * @return A pointer on the SceneInterface which instanciated the
+     *         SceneContent.
+     *
+     */
+    SceneInterface* plugin() {return m_plugin;}
+
+
+    /**
+     * Gets the SceneInterface which instanciated the SceneContent.
+     * This fonction differs from the previous one by the "const" attribute.
+     *
+     * @return A const pointer on the SceneInterface which instanciated the
+     *         SceneContent.
+     *
+     */
+    const SceneInterface* plugin() const {return m_plugin;}
+
+
+    /**
+     * Copies the content from a SceneContent.
+     *
+     * @param content A const-reference on the content to be copied.
+     *
+     * @return true if the copy suceeds, false otherwise.
+     *
+     */
+    virtual bool copy_from(const SceneContent& content) {Q_ASSERT(m_plugin==content.m_plugin); Q_UNUSED(content); return true;}
+
+
+    /**
+     * Check if 2 contents are equal.
+     *
+     * @param content A const-reference on the content to be checked.
+     * @return true if the contents are the same, false otherwise.
+     *
+     */
+    virtual bool is_equal_to(const SceneContent& content) const {return m_plugin==content.m_plugin;}
+
+
+    /**
+     * Restore the export settings from XML content.
+     *
+     * @param element Parent XML element of the export settings content.
+     *
+     */
+    virtual void initFromDOMElement(const QDomElement& element) {if (!element.isNull()) {}}
+
+
+    /**
+     * Store the current export settings as XML content.
+     *
+     * @param name XML node name of the content.
+     * @param doc XML document to store the content.
+     *
+     * @return Current export settings content as XML content.
+     *
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const { QDomElement de = doc.createElement(name); de.setAttribute("name", getFullName()); return de;}
+
+
+    /**
+     * Gets the scene name.
+     * This is the name that is in the scene list of the
+     * SceneInterface::scenes().
+     *
+     * @return the name of the scene.
+     *
+     */
+    virtual const QString& scene_name(void) const = 0;
+
+
+    /**
+     * Gets the scene full name.
+     * This name can be used in the interface of Projection Designer to define in a unique way the scene.
+     *
+     * @return The fullname of the scene.
+     *
+     */
+    QString getFullName(void) const {
+	Q_ASSERT(m_plugin);
+	QString scene_fullname = scene_name();
+	scene_fullname += " (";
+	scene_fullname += m_plugin->name();
+	scene_fullname += ")";
+	return scene_fullname;
+    }
+
+
+    /**
+     * Draws the scene.
+     * This method draws the geometric scene content. For instance, for a 
+     * standard scene, it draws the frustum in the scene.
+     *
+     */
+    virtual void draw(QGLWidget *glWidget, const float* cameraMatrix) {Q_UNUSED(glWidget);Q_UNUSED(cameraMatrix);}
+
+
+    /**
+     * Resets the content.
+     *
+     * This method was added for the grids, to fix the fact that a
+     * "New project" did not clear the grids.
+     *
+     */
+    virtual void reset (void)=0;
+
+private:
+    SceneInterface *m_plugin; ///< The SceneInterface in which the scene is.
+};
+
+/**
+ * Scene widget class implementation.
+ *
+ * Each widget has its own content. They can be retrieved using content().
+ *
+ */
+class SceneWidget: public QWidget
+{
+	Q_OBJECT
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    SceneWidget(SceneInterface *plugin=NULL, QWidget* pParent=0, Qt::WFlags flag=0): QWidget(pParent, flag), m_plugin(plugin) {Q_ASSERT(NULL!=plugin);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    virtual ~SceneWidget() {}
+
+
+    /**
+     * Gets the scene interface associated with the widget.
+     *
+     * @return The associated scene interfacec.
+     *
+     */
+    SceneInterface* plugin() {return m_plugin;}
+
+
+    /**
+     * Updates the GUI.
+     *
+     * This method *must* be implemented by derived classes.
+     *
+     * @param content The content used to update the GUI. The content can be 
+     *                NULL. In this case, the current content are used.
+     *
+     */
+    virtual void updateGUI(const SceneContent* data) = 0;
+
+
+    /**
+     * Gets the content of the widget.
+     *
+     * @return The widget content.
+     *
+     */
+    virtual const SceneContent& content(void) const = 0;
+
+
+signals:
+
+
+    /**
+     * Notify that contents have changed.
+     *
+     * @param data The new contents.
+     *
+     */
+    virtual void dataChanged(const SceneContent&)=0;
+
+private:
+
+
+    SceneInterface *m_plugin; ///< The SceneInterface that owns the Widget.
+
+};
+
+Q_DECLARE_INTERFACE(SceneInterface,
+                    "jp.orihalcon.projdesigner.SceneInterface/1.0");
+
+#endif
Index: projectionDesigner/trunk/projdesigner/include/math/ProjectionMatrix.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/math/ProjectionMatrix.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/math/ProjectionMatrix.h	(revision 4)
@@ -0,0 +1,217 @@
+#ifndef _PROJECTIONMATRIX_H_
+#define _PROJECTIONMATRIX_H_
+
+#include <QtXml>
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+
+namespace projection
+{
+
+/**
+ * Projection matrix class.
+ */
+class ProjectionMatrix
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * Default projection matrix value is : FOV=30.0, 
+     * AspectRatio=4/3, Near=0.1, Far=100.0
+     */
+    ProjectionMatrix();
+
+    /**
+     * Destructor.
+     */
+    virtual ~ProjectionMatrix();
+
+    /**
+     * Copy constructor.
+     *
+     * @param matrix Copy source matrix.
+     */
+    ProjectionMatrix(const ProjectionMatrix &matrix);
+
+    /**
+     * Set Field of View.
+     *
+     * @param fov Field of View.
+     */
+    void setFOV(float fov) { m_fov = fov; }
+
+    /**
+     * Retrieve Field of View.
+     *
+     * @return Field of View.
+     */
+    float getFOV() const { return m_fov; }
+
+    /**
+     * Set aspect ratio.
+     *
+     * @param ratio Aspect ratio.
+     */
+    void setAspectRatio(float ratio) { m_aspectRatio = ratio; }
+
+    /**
+     * Retrieve aspect ratio.
+     *
+     * @return Aspect ratio.
+     */
+    float getAspectRatio() const { return m_aspectRatio; }
+
+    /**
+     * Set near clip distance.
+     *
+     * @param Near clip distance.
+     */
+    void setNear(float nearDist) { m_near = nearDist; }
+
+    /**
+     * Retrieve near clip distance.
+     *
+     * @return Near clip distance.
+     */
+    float getNear() const { return m_near; }
+
+    /**
+     * Set far clip plane distance.
+     *
+     * @param Far clip plane distance.
+     */
+    void setFar(float farDist) { m_far = farDist; }
+
+    /**
+     * Retrieve far clip plane distance.
+     *
+     * @return Far clip plane distance.
+     */
+    float getFar() const { return m_far; }
+
+    /**
+     * Set vertical off-axis  distane on the Z=1.0 plane.
+     *
+     * @param Vertical off-axis  distane.
+     */
+    void setOffaxisX(float offaxisX) { m_offaxisX = offaxisX; }
+
+    /**
+     * Retrieve horizontal off-axis  distane on the Z=1.0 plane.
+     *
+     * @return Horizontal off-axis  distane.
+     */
+    float getOffaxisX() const { return m_offaxisX; }
+
+    /**
+     * Set horizontal off-axis  distane on the Z=1.0 plane.
+     *
+     * @param Horizontal off-axis  distane.
+     */
+    void setOffaxisY(float offaxisY) { m_offaxisY = offaxisY; }
+
+    /**
+     * Retrieve vertical off-axis  distane on the Z=1.0 plane.
+     *
+     * @return Vertical off-axis  distane.
+     */
+    float getOffaxisY() const { return m_offaxisY; }
+
+    /**
+     * Retrieve matrix values for glMultMatrixd().
+     *
+     * @return Matrix values.
+     */
+    float* getMatrix();
+
+    /**
+     * Retrieve four corner vectors.
+     *
+     * @param Four corner vectors.
+     */
+    void getCorners(gmtl::Vec3f vecs[4]) const;
+
+    /**
+     * Retrieve frustum parameters as 'Frustum left right bottom top near far;'.
+     *
+     * @param numSpaces Number of space characters for indent.
+     * @return Frustum params.
+     */
+    QString getParams(int numSpaces=0) const;
+
+    /**
+     * Assignment operator.
+     *
+     * @param m Assignment source projection matrix.
+     */
+    ProjectionMatrix& operator=(const ProjectionMatrix& m)
+    {
+        if (this != &m)
+        {
+            m_fov = m.m_fov;
+            m_aspectRatio = m.m_aspectRatio;
+            m_near = m.m_near;
+            m_far = m.m_far;
+            m_offaxisX = m.m_offaxisX;
+            m_offaxisY = m.m_offaxisY;
+        }
+        return *this;
+    }
+
+    /**
+     * Equal operator.
+     *
+     * @param a Operand projection matrix.
+     * @param b Operand projection matrix.
+     */
+    friend bool operator==(const ProjectionMatrix &a, const ProjectionMatrix &b)
+    {
+        return (a.m_fov == b.m_fov && a.m_aspectRatio == b.m_aspectRatio &&
+                a.m_near == b.m_near && a.m_far == b.m_far &&
+                a.m_offaxisX == b.m_offaxisX && a.m_offaxisY == b.m_offaxisY);
+    }
+
+    /**
+     * Not equal operator.
+     *
+     * @param a Operand projection matrix.
+     * @param b Operand projection matrix.
+     */
+    friend bool operator!=(const ProjectionMatrix &a, const ProjectionMatrix &b)
+    {
+        return !(a==b);
+    }
+
+    /**
+     * Restore the projection matrix from XML data.
+     *
+     * @param element Parent XML element of the projection matrix data.
+     */
+	virtual void initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current projection matrix as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current projection matrix data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+private:
+
+    float m_fov;            //!< Field of View (FOV).
+    float m_aspectRatio;    //!< Aspect ratio (width / height).
+    float m_near;           //!< Near clip plane distance.
+    float m_far;            //!< Far clip plane distance.
+    float m_offaxisX;       //!< Horizontal off-axis distance.
+    float m_offaxisY;       //!< Vertical off-axis distance.
+
+    float m_mat[16];        //!< Matrix values. Calculated when getMatrix() called.
+};
+
+}; // projection
+
+#endif // _PROJECTIONMATRIX_H_
Index: projectionDesigner/trunk/projdesigner/include/math/TransformMatrix.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/math/TransformMatrix.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/math/TransformMatrix.h	(revision 4)
@@ -0,0 +1,177 @@
+#ifndef _TRANSFORMMATRIX_H_
+#define _TRANSFORMMATRIX_H_
+
+#include <QtXml>
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+
+namespace projection
+{
+
+/**
+ * Transform matrix class.
+ */
+class TransformMatrix
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * Default transform matrix value is identity matrix.
+     */
+    TransformMatrix();
+
+    /**
+     * Destructor.
+     */
+    virtual ~TransformMatrix();
+
+    /**
+     * Set position of the transform matrix.
+     *
+     * @param pos Position of the transform matrix.
+     */
+    void setPosition(const gmtl::Vec3f& pos) { m_pos = pos; }
+
+    /**
+     * Retrieve the position of the transform matrix.
+     *
+     * @return Position of the transform matrix.
+     */
+    gmtl::Vec3f getPosition() const { return m_pos; }
+
+    /**
+     * Set rotation of the transform matrix.
+     *
+     * @param rot Rotation of the transform matrix.
+     */
+    void setRotation(const gmtl::Vec3f& rot) { m_rot = rot; }
+
+    /**
+     * Retrieve the rotation of the transform matrix.
+     *
+     * @return Rotation of the transform matrix.
+     */
+    gmtl::Vec3f getRotation() const { return m_rot; }
+
+    /**
+     * Set scaling of the transform matrix.
+     *
+     * @param scale Scaling of the transform matrix.
+     */
+    void setScaling(const gmtl::Vec3f& scale) { m_scale = scale; }
+
+    /**
+     * Retrieve the scaling of the transform matrix.
+     *
+     * @return Scaling of the transform matrix.
+     */
+    gmtl::Vec3f getScaling() const { return m_scale; }
+
+    /**
+     * Set whether using scale or not in the transform matrix.
+     *
+     * @param bUseScale True to use scaling in the transform matrix.
+     */
+    void setUseScaling(bool bUseScale) { m_bUseScale = bUseScale; }
+
+    /**
+     * Check whether using scale or not in the transform matrix.
+     *
+     * @return True if using scale in the transform matrix.
+     */
+    bool getUseScaling() const { return m_bUseScale; }
+
+    /**
+     * Retrieve the trasform matrix.
+     *
+     * @return Trasform matrix.
+     */
+    gmtl::Matrix44f getMatrix() const;
+
+    /**
+     * Retrieve the trasform matrix without scaling.
+     *
+     * @return Trasform matrix without scaling.
+     */
+    gmtl::Matrix44f getMatrixWOScaling() const;
+
+    /**
+    * Retrieve transform parameters like 'Rotate 45 1 0 0;'.
+    *
+    * @param numSpaces Number of space characters for indent.
+    * @return Transform params.
+    */
+    QString getParams(int numSpaces=0) const;
+
+    /**
+     * Assignment operator.
+     *
+     * @param m Assignment source transform matrix.
+     */
+    TransformMatrix& operator=(const TransformMatrix& m)
+    {
+        m_pos = m.m_pos;
+        m_rot = m.m_rot;
+        m_scale = m.m_scale;
+        return *this;
+    }
+
+    /**
+     * Equal operator.
+     *
+     * @param a Operand transform matrix.
+     * @param b Operand transform matrix.
+     */
+    friend bool operator==(const TransformMatrix &a, const TransformMatrix &b)
+    {
+        return (a.m_pos == b.m_pos && a.m_rot == b.m_rot && a.m_scale == b.m_scale);
+    }
+
+    /**
+     * Not equal operator.
+     *
+     * @param a Operand transform matrix.
+     * @param b Operand transform matrix.
+     */
+    friend bool operator!=(const TransformMatrix &a, const TransformMatrix &b)
+    {
+        return !(a==b);
+    }
+
+    /**
+     * Restore the transform matrix from XML data.
+     *
+     * @param element Parent XML element of the transform matrix data.
+     */
+	virtual void initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current transform matrix as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current transform matrix data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+    /**
+     * Reset the matrix.
+     */
+    void reset();
+
+private:
+
+    bool m_bUseScale;
+
+    gmtl::Vec3f m_pos;      //!< Position of the tranform matrix.
+	gmtl::Vec3f m_rot;      //!< Rotation of the tranform matrix.
+	gmtl::Vec3f m_scale;    //!< Scaling of the tranform matrix.
+
+    double m_mat[16];       //!< Matrix values. Calculated when getMatrix() called.
+};
+
+}; // projection
+
+#endif // _TRANSFORMMATRIX_H_
Index: projectionDesigner/trunk/projdesigner/include/screen/ScreenBox.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/screen/ScreenBox.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/screen/ScreenBox.h	(revision 4)
@@ -0,0 +1,164 @@
+#ifndef _SCREEN_BOX_H_
+#define _SCREEN_BOX_H_
+
+#include "screen/ScreenShape.h"
+
+namespace projection
+{
+
+/**
+  * Box screen class.
+  */
+class ScreenBox : public ScreenShape
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pScreen Screen data.
+     */
+    ScreenBox(Screen* pScreen);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ScreenBox();
+
+    /**
+     * Retrieve name of the sceen shape.
+     *
+     * @return Name of the screen shape.
+     */
+    QString getName() const { return "Box"; }
+
+    /**
+     * Set width of the box screen.
+     *
+     * @param width Width of the box screen.
+     */
+    void setWidth(double width);
+
+    /**
+     * Retrieve width of the box screen.
+     *
+     * @return Width of the box screen.
+     */
+    double getWidth() const { return m_width; }
+
+    /**
+     * Set height of the box screen.
+     *
+     * @param height Height of the box screen.
+     */
+    void setHeight(double height);
+
+    /**
+     * Retrieve height of the box screen.
+     *
+     * @return Height of the box screen.
+     */
+    double getHeight() const { return m_height; }
+
+    /**
+     * Set depth of the box screen.
+     *
+     * @param depth Depth of the box screen.
+     */
+    void setDepth(double depth);
+
+    /**
+     * Retrieve depth of the box screen.
+     *
+     * @return Depth of the box screen.
+     */
+    double getDepth() const { return m_depth; }
+
+    /**
+     * Set horizontal resolution of the box screen.
+     *
+     * @param resolution Horizontal resolution of the box screen.
+     */
+    void setHorResolution(unsigned int resolution);
+
+    /**
+     * Retrieve horizontal resolution of the box screen.
+     *
+     * @return Horizontal resolution of the box screen.
+     */
+    unsigned int getHorResolution() const { return m_horResolution; }
+
+    /**
+     * Set vertical resolution of the box screen.
+     *
+     * @param resolution Vertical resolution of the box screen.
+     */
+    void setVertResolution(unsigned int resolution);
+
+    /**
+     * Retrieve vertical resolution of the box screen.
+     *
+     * @return Vertical resolution of the box screen.
+     */
+    unsigned int getVertResolution() const { return m_vertResolution; }
+
+    /**
+     * Set depth resolution of the box screen.
+     *
+     * @param resolution Depth resolution of the box screen.
+     */
+    void setDepthResolution(unsigned int resolution);
+
+    /**
+     * Retrieve depth resolution of the box screen.
+     *
+     * @return Depth resolution of the box screen.
+     */
+    unsigned int getDepthResolution() const { return m_depthResolution; }
+
+    /**
+     * Retrieve bounding box of the screen shape.
+     *
+     * @param min One corner of the screen shape.
+     * @param max Another corner of the screen shape.
+     */
+	void getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max);
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen shape data.
+     */
+	virtual bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen shape data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    /**
+     * Draw the shape model in inherited class.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    void drawShape(bool bFrame);
+
+protected:
+
+    double m_width;                 //!< Width.
+    double m_height;                //!< Height.
+    double m_depth;                 //!< Depth.
+    unsigned int m_horResolution;   //!< Horizontal resolution.
+    unsigned int m_vertResolution;  //!< Vertical resolution.
+    unsigned int m_depthResolution; //!< Depth resolution.
+};
+
+}; // projection
+
+#endif // _SCREEN_BOX_H_
Index: projectionDesigner/trunk/projdesigner/include/screen/ScreenDome.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/screen/ScreenDome.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/screen/ScreenDome.h	(revision 4)
@@ -0,0 +1,149 @@
+#ifndef _SCREEN_DOME_H_
+#define _SCREEN_DOME_H_
+
+#include "screen/ScreenShape.h"
+
+namespace projection
+{
+
+/**
+  * Dome screen class.
+  */
+class ScreenDome : public ScreenShape
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pScreen Screen data.
+     */
+    ScreenDome(Screen* pScreen);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ScreenDome();
+
+    /**
+     * Retrieve name of the sceen shape.
+     *
+     * @return Name of the screen shape.
+     */
+    QString getName() const { return "Dome"; }
+
+    /**
+     * Set radius of the dome screen.
+     *
+     * @param radius Radius of the dome screen.
+     */
+    void setRadius(double radius);
+
+    /**
+     * Retrieve radius of the dome screen.
+     *
+     * @return Radius of the dome screen.
+     */
+    double getRadius() const { return m_radius; }
+
+    /**
+     * Set elevation resolution of the dome screen.
+     *
+     * @param resolution Elevation resolution of the dome screen.
+     */
+    void setElevResolution(unsigned int resolution);
+
+    /**
+     * Retrieve elevation resolution of the dome screen.
+     *
+     * @return Elevation resolution of the dome screen.
+     */
+    unsigned int getElevResolution() const { return m_elevResolution; }
+
+    /**
+     * Set azimuth resolution of the dome screen.
+     *
+     * @param resolution Azimuth resolution of the dome screen.
+     */
+    void setAzimResolution(unsigned int resolution);
+
+    /**
+     * Retrieve azimuth resolution of the dome screen.
+     *
+     * @return Azimuth resolution of the dome screen.
+     */
+    unsigned int getAzimResolution() const { return m_azimResolution; }
+
+    /**
+     * Set subdivision steps of the dome screen.
+     *
+     * @param subdiv Subdivision steps of the dome screen.
+     */
+    void setSubdivision(unsigned int subdiv);
+
+    /**
+     * Retrieve subdivision steps of the dome screen.
+     *
+     * @return Subdivision steps of the dome screen.
+     */
+    unsigned int getSubdivision() const { return m_subdiv; }
+
+    /**
+     * Select full dome or half dome.
+     *
+     * @param bFullDome True to select a full dome, False to select a half dome.
+     */
+    void setFullDome(bool bFullDome);
+
+    /**
+     * Check whether full dome or half dome.
+     *
+     * @return True is a full dome, False is a half dome.
+     */
+    bool getFullDome() const { return m_bFullDome; }
+
+    /**
+     * Retrieve bounding box of the screen shape.
+     *
+     * @param min One corner of the screen shape.
+     * @param max Another corner of the screen shape.
+     */
+	void getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max);
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen shape data.
+     */
+	virtual bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen shape data as XML data.
+     */
+	virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    /**
+     * Draw the shape model in inherited class.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    void drawShape(bool bFrame);
+
+protected:
+
+    double m_radius;                //!< Radius.
+    unsigned int m_elevResolution;  //!< Elevation resolution.
+    unsigned int m_azimResolution;  //!< Azimuth resolution.
+    int m_subdiv;                   //!< Subdivision steps.
+    bool m_bFullDome;               //!< True is a full dome, False is a half dome.
+};
+
+}; // projection
+
+#endif // _SCREEN_DOME_H_
Index: projectionDesigner/trunk/projdesigner/include/screen/ScreenModel.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/screen/ScreenModel.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/screen/ScreenModel.h	(revision 4)
@@ -0,0 +1,102 @@
+#ifndef _SCREEN_MODEL_H_
+#define _SCREEN_MODEL_H_
+
+#include "screen/ScreenShape.h"
+
+#include <QtGui>
+
+#include "glm/glm.h"
+
+// Only requiered to be able to retireve a GUI-Pointer
+#include "Screen.h"
+#include "ProjectionModel.h"
+#include "GUIControler.h"
+
+namespace projection
+{
+
+/**
+  * Model screen class.
+  */
+class ScreenModel : public ScreenShape
+{
+	Q_OBJECT 
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pScreen Screen data.
+     */
+    ScreenModel(Screen* pScreen);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ScreenModel();
+
+    /**
+     * Retrieve name of the sceen shape.
+     *
+     * @return Name of the screen shape.
+     */
+    QString getName() const { return "Model"; }
+
+    /**
+     * Load a model file.
+     *
+     * @param fileName File name of a model to load.
+     */
+    void setFileName(const QString& fileName);
+
+    /**
+     * Retrieve file name of the model.
+     *
+     * @return File name of the model.
+     */
+    QString getFileName() const;
+
+    /**
+     * Retrieve bounding box of the screen shape.
+     *
+     * @param min One corner of the screen shape.
+     * @param max Another corner of the screen shape.
+     */
+    void getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max);
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen shape data.
+     */
+    virtual bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen shape data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    /**
+     * Draw the shape model in inherited class.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    void drawShape(bool bFrame);
+
+protected:
+
+    QString m_fileName;         //!< File name of the model.
+    GLMmodel* m_pModel;         //!< glm model data structure.
+    GLuint m_modelIndex;        //!< gml model display list index.
+	Screen* m_pScreen;
+};
+
+}; // projection
+
+#endif // _SCREEN_MODEL_H_
Index: projectionDesigner/trunk/projdesigner/include/screen/ScreenPlane.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/screen/ScreenPlane.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/screen/ScreenPlane.h	(revision 4)
@@ -0,0 +1,141 @@
+#ifndef _SCREEN_PLANE_H_
+#define _SCREEN_PLANE_H_
+
+#include "screen/ScreenShape.h"
+
+namespace projection
+{
+
+/**
+  * Plane screen class.
+  */
+class ScreenPlane : public ScreenShape
+{
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pScreen Screen data.
+     */
+    ScreenPlane(Screen* pScreen);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ScreenPlane();
+
+    /**
+     * Retrieve name of the sceen shape.
+     *
+     * @return Name of the screen shape.
+     */
+    QString getName() const { return "Plane"; }
+
+    /**
+     * Set width of the plane screen.
+     *
+     * @param width Width of the plane screen.
+     */
+    void setWidth(double width);
+
+    /**
+     * Retrieve width of the plane screen.
+     *
+     * @return Width of the plane screen.
+     */
+    double getWidth() const { return m_width; }
+
+    /**
+     * Set height of the plane screen.
+     *
+     * @param height Height of the plane screen.
+     */
+    void setHeight(double height);
+
+    /**
+     * Retrieve height of the plane screen.
+     *
+     * @return Height of the plane screen.
+     */
+    double getHeight() const { return m_height; }
+
+    /**
+     * Set horizontal resolution of the plane screen.
+     *
+     * @param resolution Horizontal resolution of the plane screen.
+     */
+    void setHorResolution(unsigned int resolution);
+
+    /**
+     * Retrieve horizontal resolution of the plane screen.
+     *
+     * @return Horizontal resolution of the plane screen.
+     */
+    unsigned int getHorResolution() const { return m_horResolution; }
+
+    /**
+     * Set vertical resolution of the plane screen.
+     *
+     * @param resolution Vertical resolution of the plane screen.
+     */
+    void setVertResolution(unsigned int resolution);
+
+    /**
+     * Retrieve vertical resolution of the plane screen.
+     *
+     * @return Vertical resolution of the plane screen.
+     */
+    unsigned int getVertResolution() const { return m_vertResolution; }
+
+    /**
+     * Retrieve bounding box of the screen shape.
+     *
+     * @param min One corner of the screen shape.
+     * @param max Another corner of the screen shape.
+     */
+	void getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max);
+
+    /**
+     * Check whether the shape needs clipping for projection image.
+     *
+     * @return True if  the projection requires clipping.
+     */
+    virtual bool isClippingRequired() const { return false; }
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen shape data.
+     */
+	virtual bool initFromDOMElement(const QDomElement& element);
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen shape data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+protected:
+
+    /**
+     * Draw the shape model in inherited class.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    void drawShape(bool bFrame);
+
+protected:
+
+    double m_width;                 //!< Width.
+    double m_height;                //!< Height.
+    unsigned int m_horResolution;   //!< Horizontal resolution.
+    unsigned int m_vertResolution;  //!< Vertical resolution.
+};
+
+}; // projection
+
+#endif // _SCREEN_PLANE_H_
Index: projectionDesigner/trunk/projdesigner/include/screen/ScreenShape.h
===================================================================
--- projectionDesigner/trunk/projdesigner/include/screen/ScreenShape.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/include/screen/ScreenShape.h	(revision 4)
@@ -0,0 +1,105 @@
+#ifndef _SCREENSHAPE_H_
+#define _SCREENSHAPE_H_
+
+#include <QtGui>
+#include <QObject>
+#include <QtXml>
+#include <QtOpenGL>
+
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+
+namespace projection
+{
+class Screen;
+
+/**
+ * Screen shape base class.
+ */
+class ScreenShape : public QObject
+{
+	Q_OBJECT 
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param pScreen Screen data.
+     */
+    ScreenShape(Screen* pScreen);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ScreenShape();
+
+    /**
+     * Draw a screen with dislay list cache.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    void draw(bool bFrame);
+
+    /**
+     * Retrieve name of the sceen shape.
+     *
+     * @return Name of the screen shape.
+     */
+    virtual QString getName() const = 0;
+
+    /**
+     * Retrieve bounding box of the screen shape.
+     *
+     * @param min One corner of the screen shape.
+     * @param max Another corner of the screen shape.
+     */
+    virtual void getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max) = 0;
+
+    /**
+     * Check whether the shape needs clipping for projection image.
+     *
+     * @return True if  the projection requires clipping.
+     */
+    virtual bool isClippingRequired() const { return true; }
+
+    /**
+     * Restore the screen shape from XML data.
+     *
+     * @param element Parent XML element of the screen shape data.
+     */
+    virtual bool initFromDOMElement(const QDomElement& element) = 0;
+
+    /**
+     * Store the current screen shape as XML data.
+     *
+     * @param name XML node name of the data.
+     * @param doc XML document to store the data.
+     * @return Current screen shape data as XML data.
+     */
+    virtual QDomElement domElement(const QString& name, QDomDocument& doc) const = 0;
+
+protected:
+
+    /**
+     * Draw the shape model in inherited class.
+     *
+     * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+     */
+    virtual void drawShape(bool bFrame) = 0;
+
+    /**
+     * Notify to redraw the screen shape.
+     */
+    void notifyRedraw();
+
+protected:
+
+    Screen* m_pScreen;  //!< Screen data.
+
+    unsigned int m_dlIndex; //!< Display list index.
+    bool m_bDirty;          //!< Dirty flag. True to redraw the screen shape.
+};
+
+}; // projection
+
+#endif // _SCREENSHAPE_H_
Index: projectionDesigner/trunk/projdesigner/main.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/main.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/main.cpp	(revision 4)
@@ -0,0 +1,54 @@
+#include <qapplication.h>
+#include "ProjectionModel.h"
+#include "RSync.h"
+#include "GUIControler.h"
+#include <stdlib.h>
+#include <GL/glut.h>
+
+using namespace projection;
+
+#if defined(UNIX)
+#define stricmp strcasecmp
+#endif // UNIX
+
+int main(int argc, char** argv)
+{
+	glutInit (&argc, argv);
+
+	QApplication app(argc,argv);
+
+    //app.setStyle("windows");
+    //app.setStyle("plastique");
+
+	ProjectionModel model;
+
+    bool bServer = true;
+    QString address = model.getRSync()->getHostName();
+    int portNo = DEFAULT_PORT_NO;
+    QString fileName;
+    for (int i=1; i<argc; ++i)
+    {
+        if (_stricmp(argv[i], "-c") == 0 || _stricmp(argv[i], "-client") == 0)
+            bServer = false;
+        else if (_stricmp(argv[i], "-address") == 0 && i+1 < argc)
+            address = argv[i+1];
+        else if ((_stricmp(argv[i], "-port") == 0 || _stricmp(argv[i], "-portno") == 0) && i+1 < argc)
+		{
+            portNo = atoi(argv[i+1]);
+			i++;	// <== Don't parse Portnumber again.
+		}
+        else
+            fileName = argv[i];
+    }
+
+    if (bServer)
+    {
+        model.initServer(portNo);
+        if (!fileName.isEmpty())
+            model.getGUI()->loadFile(fileName);
+    }
+    else
+        model.initClient(address, portNo);
+
+	return app.exec();
+}
Index: projectionDesigner/trunk/projdesigner/projdesigner.pro
===================================================================
--- projectionDesigner/trunk/projdesigner/projdesigner.pro	(revision 4)
+++ projectionDesigner/trunk/projdesigner/projdesigner.pro	(revision 4)
@@ -0,0 +1,122 @@
+TEMPLATE = app
+
+QT += xml opengl network
+
+unix {
+  DEFINES += UNIX
+  INCLUDEPATH += ${HOME}/usr/include
+  LIBS += -L${HOME}/usr/lib
+}
+
+TARGET = projdesigner
+
+LIBS += -lglut
+LIBS += -L../projdesignerplugins/defaultplugin -lprojdesigner_default
+
+INCLUDEPATH += ..
+
+DEPENDPATH += . \
+              include \
+              src \
+              include/gui \
+              include/math \
+              include/screen \
+              src/gui \
+              src/math \
+              src/screen
+
+INCLUDEPATH += . \
+               include \
+               include/math \
+               include/gui \
+               include/screen
+
+HEADERS += include/gui/plugindialog.h \
+           include/interfaces.h \
+           include/Channel.h \
+           include/Exporter.h \
+           include/Frustum.h \
+           include/GUIControler.h \
+           include/Version.h \
+           include/ProjectionModel.h \
+           include/RSync.h \
+           include/Scene.h \
+           include/Screen.h \
+           include/Warp.h \
+           include/gui/Defines.h \
+           include/gui/QGLViewerWidget.h \
+           include/gui/QChannelManagerWidget.h \
+           include/gui/QChannelWidget.h \
+           include/gui/QClientWindow.h \
+           include/gui/QDesignViewWidget.h \
+           include/gui/QDesignViewWindow.h \
+           include/gui/QPanelWidget.h \
+           include/gui/QPreferenceDialog.h \
+           include/gui/QProjectionMatrixWidget.h \
+           include/gui/QProjectorWindow.h \
+           include/gui/QSceneViewerWindow.h \
+           include/gui/QSceneWidget.h \
+           include/gui/QScreenWidget.h \
+           include/gui/QTransformMatrixWidget.h \
+           include/math/ProjectionMatrix.h \
+           include/math/TransformMatrix.h \
+           include/screen/ScreenBox.h \
+           include/screen/ScreenDome.h \
+           include/screen/ScreenModel.h \
+           include/screen/ScreenPlane.h \
+           include/screen/ScreenShape.h
+FORMS += include/gui/qchannelmanagerwidget.ui \
+         include/gui/qchannelwidget.ui \
+         include/gui/qclientwindow.ui \
+         include/gui/qdesignviewwindow.ui \
+         include/gui/qpanelwidget.ui \
+         include/gui/qpreferencedialog.ui \
+         include/gui/qprojectionmatrixwidget.ui \
+         include/gui/qscenewidget.ui \
+         include/gui/qscreenwidget.ui \
+         include/gui/qsetupdialog.ui \
+         include/gui/qtransformmatrixwidget.ui
+
+SOURCES += src/gui/plugindialog.cpp \
+           main.cpp \
+           src/Channel.cpp \
+           src/Exporter.cpp \
+           src/Frustum.cpp \
+           src/GUIControler.cpp \
+           src/Version.cpp \
+           src/ProjectionModel.cpp \
+           src/RSync.cpp \
+           src/Scene.cpp \
+           src/Screen.cpp \
+           src/Warp.cpp \
+           src/gui/Defines.cpp \
+           src/gui/QGLViewerWidget.cpp \
+           src/gui/QChannelManagerWidget.cpp \
+           src/gui/QChannelWidget.cpp \
+           src/gui/QClientWindow.cpp \
+           src/gui/QDesignViewWidget.cpp \
+           src/gui/QDesignViewWindow.cpp \
+           src/gui/QPanelWidget.cpp \
+           src/gui/QPreferenceDialog.cpp \
+           src/gui/QProjectionMatrixWidget.cpp \
+           src/gui/QProjectorWindow.cpp \
+           src/gui/QSceneViewerWindow.cpp \
+           src/gui/QSceneWidget.cpp \
+           src/gui/QScreenWidget.cpp \
+           src/gui/QTransformMatrixWidget.cpp \
+           src/math/ProjectionMatrix.cpp \
+           src/math/TransformMatrix.cpp \
+           src/screen/ScreenBox.cpp \
+           src/screen/ScreenDome.cpp \
+           src/screen/ScreenModel.cpp \
+           src/screen/ScreenPlane.cpp \
+           src/screen/ScreenShape.cpp
+
+DESTDIR=../bin/
+
+target.path = /usr/local/bin/
+INSTALLS += target
+
+
+#Resource file(s)
+RESOURCES += ./projdesigner.qrc
Index: projectionDesigner/trunk/projdesigner/projdesigner.qrc
===================================================================
--- projectionDesigner/trunk/projdesigner/projdesigner.qrc	(revision 4)
+++ projectionDesigner/trunk/projdesigner/projdesigner.qrc	(revision 4)
@@ -0,0 +1,19 @@
+<RCC>
+    <qresource prefix="/new/prefix1" >
+        <file>Resources/aboutQt.png</file>
+        <file>Resources/blendMode.png</file>
+        <file>Resources/distortionMode.png</file>
+        <file>Resources/exit.png</file>
+        <file>Resources/exitAll.png</file>
+        <file>Resources/export.png</file>
+        <file>Resources/help.png</file>
+        <file>Resources/new.png</file>
+        <file>Resources/open.png</file>
+        <file>Resources/plugins.png</file>
+        <file>Resources/projDesigner.png</file>
+        <file>Resources/save.png</file>
+        <file>Resources/saveAs.png</file>
+        <file>Resources/settings.png</file>
+        <file>Resources/sync.png</file>
+    </qresource>
+</RCC>
Index: projectionDesigner/trunk/projdesigner/projdesigner.vcproj
===================================================================
--- projectionDesigner/trunk/projdesigner/projdesigner.vcproj	(revision 4)
+++ projectionDesigner/trunk/projdesigner/projdesigner.vcproj	(revision 4)
@@ -0,0 +1,2239 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="projdesigner"
+	ProjectGUID="{4418A7F1-9C0E-31B2-B8A2-913D1394330B}"
+	RootNamespace="projdesigner"
+	Keyword="Qt4VSv1.0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="."
+			IntermediateDirectory="debug\"
+			ConfigurationType="1"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -w34100 -w34189 -Zm200 -w34100 -w34189 -w34100 -w34189"
+				Optimization="4"
+				AdditionalIncludeDirectories="&quot;$(QTDIR)\include\QtCore&quot;,&quot;$(QTDIR)\include\QtNetwork&quot;,&quot;$(QTDIR)\include\QtGui&quot;,&quot;$(QTDIR)\include\QtOpenGL&quot;,&quot;$(QTDIR)\include\QtXml&quot;,&quot;$(QTDIR)\include&quot;,&quot;..&quot;,&quot;.&quot;,&quot;include&quot;,&quot;include\math&quot;,&quot;include\gui&quot;,&quot;include\screen&quot;,&quot;$(QTDIR)\include\ActiveQt&quot;,&quot;debug&quot;,&quot;.&quot;,$(QTDIR)\mkspecs\win32-msvc2005"
+				PreprocessorDefinitions="_WINDOWS,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_DLL,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_NETWORK_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				TreatWChar_tAsBuiltInType="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="debug\"
+				ObjectFile="debug\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_WINDOWS,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_DLL,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_NETWORK_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT,_DEBUG"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				IgnoreImportLibrary="true"
+				AdditionalOptions="&quot;/MANIFESTDEPENDENCY:type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos; processorArchitecture=&apos;*&apos;&quot; &quot;/MANIFESTDEPENDENCY:type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos; processorArchitecture=&apos;*&apos;&quot;"
+				AdditionalDependencies="opengl32.lib glu32.lib gdi32.lib user32.lib $(QTDIR)\lib\qtmaind.lib glut32.lib projdesigner_default.lib $(QTDIR)\lib\QtXmld4.lib $(QTDIR)\lib\QtOpenGLd4.lib $(QTDIR)\lib\QtGuid4.lib $(QTDIR)\lib\QtNetworkd4.lib $(QTDIR)\lib\QtCored4.lib"
+				OutputFile="..\bin\projdesigner.exe"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="$(QTDIR)\lib,../projdesignerplugins/defaultplugin"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=""
+				SubSystem="2"
+				LinkTimeCodeGeneration="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="."
+			IntermediateDirectory="release\"
+			ConfigurationType="1"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -w34100 -w34189 -Zm200 -w34100 -w34189 -w34100 -w34189"
+				Optimization="2"
+				WholeProgramOptimization="true"
+				AdditionalIncludeDirectories="&quot;$(QTDIR)\include\QtCore&quot;,&quot;$(QTDIR)\include\QtNetwork&quot;,&quot;$(QTDIR)\include\QtGui&quot;,&quot;$(QTDIR)\include\QtOpenGL&quot;,&quot;$(QTDIR)\include\QtXml&quot;,&quot;$(QTDIR)\include&quot;,&quot;..&quot;,&quot;.&quot;,&quot;include&quot;,&quot;include\math&quot;,&quot;include\gui&quot;,&quot;include\screen&quot;,&quot;$(QTDIR)\include\ActiveQt&quot;,&quot;release&quot;,&quot;.&quot;,$(QTDIR)\mkspecs\win32-msvc2005"
+				PreprocessorDefinitions="QT_NO_DEBUG,NDEBUG,_WINDOWS,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_DLL,QT_NO_DEBUG,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_NETWORK_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT,NDEBUG"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				TreatWChar_tAsBuiltInType="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="release\"
+				ObjectFile="release\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="QT_NO_DEBUG,NDEBUG,_WINDOWS,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_DLL,QT_NO_DEBUG,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_NETWORK_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				IgnoreImportLibrary="true"
+				AdditionalOptions="&quot;/MANIFESTDEPENDENCY:type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos; processorArchitecture=&apos;*&apos;&quot; &quot;/MANIFESTDEPENDENCY:type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos; processorArchitecture=&apos;*&apos;&quot;"
+				AdditionalDependencies="opengl32.lib glu32.lib gdi32.lib user32.lib $(QTDIR)\lib\qtmain.lib glut32.lib projdesigner_default.lib $(QTDIR)\lib\QtXml4.lib $(QTDIR)\lib\QtOpenGL4.lib $(QTDIR)\lib\QtGui4.lib $(QTDIR)\lib\QtNetwork4.lib $(QTDIR)\lib\QtCore4.lib"
+				OutputFile="..\bin\projdesigner.exe"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="$(QTDIR)\lib,../projdesignerplugins/defaultplugin"
+				GenerateDebugInformation="false"
+				ProgramDatabaseFile=""
+				SubSystem="2"
+				LinkTimeCodeGeneration="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="src\Channel.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\Defines.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Exporter.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Frustum.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\GUIControler.cpp"
+				>
+			</File>
+			<File
+				RelativePath="main.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\plugindialog.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\math\ProjectionMatrix.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\ProjectionModel.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QChannelManagerWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QChannelWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QClientWindow.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QDesignViewWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QDesignViewWindow.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QGLViewerWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QPanelWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QPreferenceDialog.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QProjectionMatrixWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QProjectorWindow.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QSceneViewerWindow.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QSceneWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QScreenWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\gui\QTransformMatrixWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\RSync.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Scene.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Screen.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\screen\ScreenBox.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\screen\ScreenDome.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\screen\ScreenModel.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\screen\ScreenPlane.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\screen\ScreenShape.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\math\TransformMatrix.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Version.cpp"
+				>
+			</File>
+			<File
+				RelativePath="src\Warp.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="include\Channel.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Channel.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Channel.h -o debug\moc_Channel.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Channel.h"
+						Outputs="debug\moc_Channel.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Channel.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Channel.h -o release\moc_Channel.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Channel.h"
+						Outputs="release\moc_Channel.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\Defines.h"
+				>
+			</File>
+			<File
+				RelativePath="include\Exporter.h"
+				>
+			</File>
+			<File
+				RelativePath="include\Frustum.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Frustum.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Frustum.h -o debug\moc_Frustum.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Frustum.h"
+						Outputs="debug\moc_Frustum.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Frustum.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Frustum.h -o release\moc_Frustum.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Frustum.h"
+						Outputs="release\moc_Frustum.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\GUIControler.h"
+				>
+			</File>
+			<File
+				RelativePath="include\interfaces.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing interfaces.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\debug\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\interfaces.h&quot; -o &quot;$(ConfigurationName)\moc_interfaces.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\interfaces.h"
+						Outputs="&quot;$(ConfigurationName)\moc_interfaces.cpp&quot;"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing interfaces.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -DQT_NO_DEBUG -DNDEBUG -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DNDEBUG -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\release\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\interfaces.h&quot; -o &quot;$(ConfigurationName)\moc_interfaces.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\interfaces.h"
+						Outputs="&quot;$(ConfigurationName)\moc_interfaces.cpp&quot;"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\plugindialog.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\plugindialog.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\plugindialog.h -o debug\moc_plugindialog.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\plugindialog.h"
+						Outputs="debug\moc_plugindialog.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\plugindialog.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\plugindialog.h -o release\moc_plugindialog.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\plugindialog.h"
+						Outputs="release\moc_plugindialog.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\math\ProjectionMatrix.h"
+				>
+			</File>
+			<File
+				RelativePath="include\ProjectionModel.h"
+				>
+			</File>
+			<File
+				RelativePath="include\gui\QChannelManagerWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QChannelManagerWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QChannelManagerWidget.h -o debug\moc_QChannelManagerWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QChannelManagerWidget.h"
+						Outputs="debug\moc_QChannelManagerWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QChannelManagerWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QChannelManagerWidget.h -o release\moc_QChannelManagerWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QChannelManagerWidget.h"
+						Outputs="release\moc_QChannelManagerWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QChannelWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QChannelWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QChannelWidget.h -o debug\moc_QChannelWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QChannelWidget.h"
+						Outputs="debug\moc_QChannelWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QChannelWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QChannelWidget.h -o release\moc_QChannelWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QChannelWidget.h"
+						Outputs="release\moc_QChannelWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QClientWindow.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QClientWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QClientWindow.h -o debug\moc_QClientWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QClientWindow.h"
+						Outputs="debug\moc_QClientWindow.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QClientWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QClientWindow.h -o release\moc_QClientWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QClientWindow.h"
+						Outputs="release\moc_QClientWindow.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QDesignViewWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QDesignViewWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QDesignViewWidget.h -o debug\moc_QDesignViewWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QDesignViewWidget.h"
+						Outputs="debug\moc_QDesignViewWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QDesignViewWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QDesignViewWidget.h -o release\moc_QDesignViewWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QDesignViewWidget.h"
+						Outputs="release\moc_QDesignViewWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QDesignViewWindow.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QDesignViewWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QDesignViewWindow.h -o debug\moc_QDesignViewWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QDesignViewWindow.h"
+						Outputs="debug\moc_QDesignViewWindow.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QDesignViewWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QDesignViewWindow.h -o release\moc_QDesignViewWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QDesignViewWindow.h"
+						Outputs="release\moc_QDesignViewWindow.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QGLViewerWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QGLViewerWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QGLViewerWidget.h -o debug\moc_QGLViewerWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QGLViewerWidget.h"
+						Outputs="debug\moc_QGLViewerWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QGLViewerWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QGLViewerWidget.h -o release\moc_QGLViewerWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QGLViewerWidget.h"
+						Outputs="release\moc_QGLViewerWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QPanelWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QPanelWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QPanelWidget.h -o debug\moc_QPanelWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QPanelWidget.h"
+						Outputs="debug\moc_QPanelWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QPanelWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QPanelWidget.h -o release\moc_QPanelWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QPanelWidget.h"
+						Outputs="release\moc_QPanelWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QPreferenceDialog.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QPreferenceDialog.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QPreferenceDialog.h -o debug\moc_QPreferenceDialog.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QPreferenceDialog.h"
+						Outputs="debug\moc_QPreferenceDialog.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QPreferenceDialog.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QPreferenceDialog.h -o release\moc_QPreferenceDialog.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QPreferenceDialog.h"
+						Outputs="release\moc_QPreferenceDialog.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QProjectionMatrixWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QProjectionMatrixWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QProjectionMatrixWidget.h -o debug\moc_QProjectionMatrixWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QProjectionMatrixWidget.h"
+						Outputs="debug\moc_QProjectionMatrixWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QProjectionMatrixWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QProjectionMatrixWidget.h -o release\moc_QProjectionMatrixWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QProjectionMatrixWidget.h"
+						Outputs="release\moc_QProjectionMatrixWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QProjectorWindow.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QProjectorWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QProjectorWindow.h -o debug\moc_QProjectorWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QProjectorWindow.h"
+						Outputs="debug\moc_QProjectorWindow.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QProjectorWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QProjectorWindow.h -o release\moc_QProjectorWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QProjectorWindow.h"
+						Outputs="release\moc_QProjectorWindow.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QSceneViewerWindow.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QSceneViewerWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QSceneViewerWindow.h -o debug\moc_QSceneViewerWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QSceneViewerWindow.h"
+						Outputs="debug\moc_QSceneViewerWindow.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QSceneViewerWindow.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QSceneViewerWindow.h -o release\moc_QSceneViewerWindow.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QSceneViewerWindow.h"
+						Outputs="release\moc_QSceneViewerWindow.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QSceneWidget.h -o debug\moc_QSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QSceneWidget.h"
+						Outputs="debug\moc_QSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QSceneWidget.h -o release\moc_QSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QSceneWidget.h"
+						Outputs="release\moc_QSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QScreenWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QScreenWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QScreenWidget.h -o debug\moc_QScreenWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QScreenWidget.h"
+						Outputs="debug\moc_QScreenWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QScreenWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QScreenWidget.h -o release\moc_QScreenWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QScreenWidget.h"
+						Outputs="release\moc_QScreenWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\QTransformMatrixWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QTransformMatrixWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QTransformMatrixWidget.h -o debug\moc_QTransformMatrixWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QTransformMatrixWidget.h"
+						Outputs="debug\moc_QTransformMatrixWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\gui\QTransformMatrixWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\gui\QTransformMatrixWidget.h -o release\moc_QTransformMatrixWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\gui\QTransformMatrixWidget.h"
+						Outputs="release\moc_QTransformMatrixWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\RSync.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\RSync.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\RSync.h -o debug\moc_RSync.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\RSync.h"
+						Outputs="debug\moc_RSync.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\RSync.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\RSync.h -o release\moc_RSync.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\RSync.h"
+						Outputs="release\moc_RSync.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\Scene.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Scene.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Scene.h -o debug\moc_Scene.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Scene.h"
+						Outputs="debug\moc_Scene.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Scene.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Scene.h -o release\moc_Scene.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Scene.h"
+						Outputs="release\moc_Scene.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\Screen.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Screen.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Screen.h -o debug\moc_Screen.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Screen.h"
+						Outputs="debug\moc_Screen.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC include\Screen.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtNetwork&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..&quot; -I&quot;.&quot; -I&quot;include&quot; -I&quot;include\math&quot; -I&quot;include\gui&quot; -I&quot;include\screen&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 include\Screen.h -o release\moc_Screen.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;include\Screen.h"
+						Outputs="release\moc_Screen.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\screen\ScreenBox.h"
+				>
+			</File>
+			<File
+				RelativePath="include\screen\ScreenDome.h"
+				>
+			</File>
+			<File
+				RelativePath="include\screen\ScreenModel.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing ScreenModel.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\debug\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\screen\ScreenModel.h&quot; -o &quot;$(ConfigurationName)\moc_ScreenModel.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\screen\ScreenModel.h"
+						Outputs="&quot;$(ConfigurationName)\moc_ScreenModel.cpp&quot;"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing ScreenModel.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -DQT_NO_DEBUG -DNDEBUG -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DNDEBUG -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\release\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\screen\ScreenModel.h&quot; -o &quot;$(ConfigurationName)\moc_ScreenModel.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\screen\ScreenModel.h"
+						Outputs="&quot;$(ConfigurationName)\moc_ScreenModel.cpp&quot;"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\screen\ScreenPlane.h"
+				>
+			</File>
+			<File
+				RelativePath="include\screen\ScreenShape.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing ScreenShape.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\debug\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\screen\ScreenShape.h&quot; -o &quot;$(ConfigurationName)\moc_ScreenShape.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\screen\ScreenShape.h"
+						Outputs="&quot;$(ConfigurationName)\moc_ScreenShape.cpp&quot;"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Moc&apos;ing ScreenShape.h..."
+						CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot;  -DQT_NO_DEBUG -DNDEBUG -D_WINDOWS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DNDEBUG -I&quot;$(QTDIR)\include\QtCore\.&quot; -I&quot;$(QTDIR)\include\QtNetwork\.&quot; -I&quot;$(QTDIR)\include\QtGui\.&quot; -I&quot;$(QTDIR)\include\QtOpenGL\.&quot; -I&quot;$(QTDIR)\include\QtXml\.&quot; -I&quot;$(QTDIR)\include\.&quot; -I&quot;.\..\.&quot; -I&quot;.\.&quot; -I&quot;.\include\.&quot; -I&quot;.\include\math\.&quot; -I&quot;.\include\gui\.&quot; -I&quot;.\include\screen\.&quot; -I&quot;$(QTDIR)\include\ActiveQt\.&quot; -I&quot;.\release\.&quot; -I&quot;.\.&quot; -I&quot;$(QTDIR)\mkspecs\win32-msvc2005\.&quot; &quot;include\screen\ScreenShape.h&quot; -o &quot;$(ConfigurationName)\moc_ScreenShape.cpp&quot;&#x0D;&#x0A;"
+						AdditionalDependencies="&quot;$(QTDIR)\bin\moc.exe&quot;;include\screen\ScreenShape.h"
+						Outputs="&quot;$(ConfigurationName)\moc_ScreenShape.cpp&quot;"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\math\TransformMatrix.h"
+				>
+			</File>
+			<File
+				RelativePath="include\Version.h"
+				>
+			</File>
+			<File
+				RelativePath="include\Warp.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Generated Files"
+			Filter="cpp;c;cxx;moc;h;def;odl;idl;res;"
+			UniqueIdentifier="{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}"
+			>
+			<File
+				RelativePath="debug\moc_Channel.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_Channel.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_Frustum.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_Frustum.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\release\moc_interfaces.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\debug\moc_interfaces.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_plugindialog.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_plugindialog.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QChannelManagerWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QChannelManagerWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QChannelWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QChannelWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QClientWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QClientWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QDesignViewWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QDesignViewWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QDesignViewWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QDesignViewWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QGLViewerWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QGLViewerWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QPanelWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QPanelWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QPreferenceDialog.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QPreferenceDialog.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QProjectionMatrixWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QProjectionMatrixWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QProjectorWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QProjectorWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QSceneViewerWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QSceneViewerWindow.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QScreenWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QScreenWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_QTransformMatrixWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_QTransformMatrixWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_RSync.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_RSync.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_Scene.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_Scene.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_Screen.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_Screen.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\release\moc_ScreenModel.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\debug\moc_ScreenModel.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\release\moc_ScreenShape.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\debug\moc_ScreenShape.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\generatedfiles\qrc_projdesigner.cpp"
+				>
+			</File>
+			<File
+				RelativePath="ui_qchannelmanagerwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qchannelwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qclientwindow.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qdesignviewwindow.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qpanelwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qpreferencedialog.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qprojectionmatrixwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qscreenwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qsetupdialog.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_qtransformmatrixwidget.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Form Files"
+			Filter="ui"
+			UniqueIdentifier="{99349809-55BA-4b9d-BF79-8FDBB0286EB3}"
+			ParseFiles="false"
+			>
+			<File
+				RelativePath="include\gui\qchannelmanagerwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qchannelmanagerwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qchannelmanagerwidget.ui -o ui_qchannelmanagerwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qchannelmanagerwidget.ui"
+						Outputs="ui_qchannelmanagerwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qchannelmanagerwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qchannelmanagerwidget.ui -o ui_qchannelmanagerwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qchannelmanagerwidget.ui"
+						Outputs="ui_qchannelmanagerwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qchannelwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qchannelwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qchannelwidget.ui -o ui_qchannelwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qchannelwidget.ui"
+						Outputs="ui_qchannelwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qchannelwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qchannelwidget.ui -o ui_qchannelwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qchannelwidget.ui"
+						Outputs="ui_qchannelwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qclientwindow.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qclientwindow.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qclientwindow.ui -o ui_qclientwindow.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qclientwindow.ui"
+						Outputs="ui_qclientwindow.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qclientwindow.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qclientwindow.ui -o ui_qclientwindow.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qclientwindow.ui"
+						Outputs="ui_qclientwindow.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qdesignviewwindow.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qdesignviewwindow.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qdesignviewwindow.ui -o ui_qdesignviewwindow.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qdesignviewwindow.ui"
+						Outputs="ui_qdesignviewwindow.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qdesignviewwindow.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qdesignviewwindow.ui -o ui_qdesignviewwindow.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qdesignviewwindow.ui"
+						Outputs="ui_qdesignviewwindow.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qpanelwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qpanelwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qpanelwidget.ui -o ui_qpanelwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qpanelwidget.ui"
+						Outputs="ui_qpanelwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qpanelwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qpanelwidget.ui -o ui_qpanelwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qpanelwidget.ui"
+						Outputs="ui_qpanelwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qpreferencedialog.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qpreferencedialog.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qpreferencedialog.ui -o ui_qpreferencedialog.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qpreferencedialog.ui"
+						Outputs="ui_qpreferencedialog.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qpreferencedialog.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qpreferencedialog.ui -o ui_qpreferencedialog.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qpreferencedialog.ui"
+						Outputs="ui_qpreferencedialog.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qprojectionmatrixwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qprojectionmatrixwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qprojectionmatrixwidget.ui -o ui_qprojectionmatrixwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qprojectionmatrixwidget.ui"
+						Outputs="ui_qprojectionmatrixwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qprojectionmatrixwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qprojectionmatrixwidget.ui -o ui_qprojectionmatrixwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qprojectionmatrixwidget.ui"
+						Outputs="ui_qprojectionmatrixwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qscenewidget.ui -o ui_qscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qscenewidget.ui"
+						Outputs="ui_qscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qscenewidget.ui -o ui_qscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qscenewidget.ui"
+						Outputs="ui_qscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qscreenwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qscreenwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qscreenwidget.ui -o ui_qscreenwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qscreenwidget.ui"
+						Outputs="ui_qscreenwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qscreenwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qscreenwidget.ui -o ui_qscreenwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qscreenwidget.ui"
+						Outputs="ui_qscreenwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qsetupdialog.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qsetupdialog.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qsetupdialog.ui -o ui_qsetupdialog.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qsetupdialog.ui"
+						Outputs="ui_qsetupdialog.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qsetupdialog.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qsetupdialog.ui -o ui_qsetupdialog.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qsetupdialog.ui"
+						Outputs="ui_qsetupdialog.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="include\gui\qtransformmatrixwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qtransformmatrixwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qtransformmatrixwidget.ui -o ui_qtransformmatrixwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qtransformmatrixwidget.ui"
+						Outputs="ui_qtransformmatrixwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC include\gui\qtransformmatrixwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe include\gui\qtransformmatrixwidget.ui -o ui_qtransformmatrixwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;include\gui\qtransformmatrixwidget.ui"
+						Outputs="ui_qtransformmatrixwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="qrc;*"
+			UniqueIdentifier="{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}"
+			ParseFiles="false"
+			>
+			<File
+				RelativePath=".\Resources\aboutQt.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\blendMode.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\distortionMode.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\exit.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\exitAll.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\export.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\help.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\new.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\open.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\plugins.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\projDesigner.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\projdesigner.qrc"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Rcc&apos;ing projdesigner.qrc..."
+						CommandLine="&quot;$(QTDIR)\bin\rcc.exe&quot; -name &quot;projdesigner&quot; -no-compress &quot;.\projdesigner.qrc&quot; -o .\GeneratedFiles\qrc_projdesigner.cpp&#x0D;&#x0A;"
+						AdditionalDependencies=".\projdesigner.qrc;.\Resources\aboutQt.png;.\Resources\blendMode.png;.\Resources\distortionMode.png;.\Resources\exit.png;.\Resources\exitAll.png;.\Resources\export.png;.\Resources\help.png;.\Resources\new.png;.\Resources\open.png;.\Resources\plugins.png;.\Resources\projDesigner.png;.\Resources\save.png;.\Resources\saveAs.png;.\Resources\settings.png;.\Resources\sync.png"
+						Outputs=".\GeneratedFiles\qrc_projdesigner.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Rcc&apos;ing projdesigner.qrc..."
+						CommandLine="&quot;$(QTDIR)\bin\rcc.exe&quot; -name &quot;projdesigner&quot; -no-compress &quot;.\projdesigner.qrc&quot; -o .\GeneratedFiles\qrc_projdesigner.cpp&#x0D;&#x0A;"
+						AdditionalDependencies=".\projdesigner.qrc;.\Resources\aboutQt.png;.\Resources\blendMode.png;.\Resources\distortionMode.png;.\Resources\exit.png;.\Resources\exitAll.png;.\Resources\export.png;.\Resources\help.png;.\Resources\new.png;.\Resources\open.png;.\Resources\plugins.png;.\Resources\projDesigner.png;.\Resources\save.png;.\Resources\saveAs.png;.\Resources\settings.png;.\Resources\sync.png"
+						Outputs=".\GeneratedFiles\qrc_projdesigner.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\save.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\saveAs.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\settings.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\Resources\sync.png"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+		<Global
+			Name="QtVersion"
+			Value="4.5.1"
+		/>
+	</Globals>
+</VisualStudioProject>
Index: projectionDesigner/trunk/projdesigner/src/Channel.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Channel.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Channel.cpp	(revision 4)
@@ -0,0 +1,1094 @@
+#include "ProjectionModel.h"
+#include "Scene.h"
+#include "Screen.h"
+#include "Warp.h"
+#include "RSync.h"
+#include "Exporter.h"
+#include "GUIControler.h"
+#include "Channel.h"
+
+#include <GL/glext.h>
+
+#include <QGLPixelBuffer>
+
+#include "gui/QDesignViewWindow.h"
+
+#define RAD(x) (((x)*2.0f*M_PI/360.0f)-2*M_PI*((int)((x)/360.0f))) // Deg -> Rad
+#define DEG(x) ((x)/M_PI*180.0)
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor.
+ *
+ * @param pModel Projection model.
+ */
+Channel::Channel(ProjectionModel* pModel) : QObject()
+{
+    m_pModel = pModel;
+
+    m_name = m_pModel->getUniqueName("unnamed", this);
+
+    m_bOverlayName = false;
+    m_overlayImageTexIndex = 0;
+
+    // remote parameters
+    m_remoteHostName = "";
+    m_bRemoteFullScreen = false;
+    m_remoteScreen = 1;
+
+    // frustum shape objects
+    m_projector.setColor(QColor(0, 0, 255));
+    m_view.setColor(QColor(255, 255, 0));
+    m_view.setShow(false);
+    m_view.setShowArea(false);
+    m_bShowProjectedScene = false;
+
+    connect(&m_view, SIGNAL(dataChanged()), this, SLOT(updateData()));
+
+    // off-screen buffer to render the scene
+    m_pSceneBuffer = NULL;
+    m_sceneTextureID = 0;
+
+    // distortion map warping
+    m_pDistWarp = new Warp;
+    m_pDistWarp->setShowCtrlPoints(m_pModel->getRSync()->isServer());
+    m_pDistWarp->setEnabled(false);
+
+    // blend map warping
+    m_pBlendWarp = new Warp;
+    m_pBlendWarp->setShowCtrlPoints(m_pModel->getRSync()->isServer());
+    m_pBlendWarp->setNumCtrlPoints(8);
+
+    // off-screen buffer for warping
+    m_pWarpBuffer = NULL;
+    m_warpTextureID = 0;
+
+	m_projectorData=NULL;
+
+	setProjector();
+
+	// We let the default constructor for m_projectorTransformMatrix
+}
+
+/**
+ * Destructor.
+ */
+Channel::~Channel()
+{
+    if (m_pBlendWarp)
+        delete m_pBlendWarp;
+
+    if (m_pDistWarp)
+        delete m_pDistWarp;
+
+    if (m_pSceneBuffer)
+    {
+        m_pSceneBuffer->releaseFromDynamicTexture();
+        glDeleteTextures(1, &m_sceneTextureID);
+        delete m_pSceneBuffer;
+    }
+
+    if (m_pWarpBuffer)
+    {
+        m_pWarpBuffer->releaseFromDynamicTexture();
+        glDeleteTextures(1, &m_warpTextureID);
+        delete m_pWarpBuffer;
+    }
+
+    if (glIsTexture(m_overlayImageTexIndex))
+        glDeleteTextures(1, &m_overlayImageTexIndex);
+
+	if (m_projectorData)
+			delete m_projectorData;
+}
+
+/**
+ * Render the scene to a texture.
+ */
+void Channel::renderSceneToViewBuffer()
+{
+    // client cares its projector window only
+    if (!m_pModel->getRSync()->isServer() &&
+        getRemoteHostName() != m_pModel->getRSync()->getHostName())
+        return;
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    if (!m_pSceneBuffer)
+    {
+        m_pSceneBuffer = new QGLPixelBuffer(
+                           m_pModel->getScreen()->getBufferWidth(),
+                           m_pModel->getScreen()->getBufferHeight(),
+                           QGLFormat::defaultFormat(), m_pModel->getGUI()->getGLWidget());
+        m_pModel->activateRenderContext();
+        m_sceneTextureID = m_pSceneBuffer->generateDynamicTexture();
+        m_pSceneBuffer->bindToDynamicTexture(m_sceneTextureID);
+    }
+    m_pSceneBuffer->makeCurrent();
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    glClearColor(0.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glViewport(0, 0, m_pModel->getScreen()->getBufferWidth(), m_pModel->getScreen()->getBufferHeight());
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glMultMatrixf(m_view.getProjectionMatrix().getMatrix());
+
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+
+    glMultMatrixf(invert(m_view.getTransformMatrix().getMatrix()).getData());
+
+    glMultMatrixf(invert(m_pModel->getScene()->getCameraMatrix()).getData());
+
+    m_pModel->getScene()->draw();
+
+    glPopMatrix();
+
+    glPopAttrib();
+
+    m_pSceneBuffer->updateDynamicTexture(m_sceneTextureID);
+
+    m_pModel->activateRenderContext();
+
+    glPopAttrib();
+}
+
+/**
+ * Render the screen viewing from the projector.
+ */
+void Channel::draw(CHANNEL_DRAWMODE drawMode)
+{
+    // if distortion map warping is needed, render to off-screen buffer
+    if (m_pDistWarp->getEnabled() ||
+        drawMode == CHANNEL_DRAWMODE_DESIGN_BLENDMAP ||
+        drawMode == CHANNEL_DRAWMODE_EXPORT_BLENDMAP)
+        getWarpBuffer()->makeCurrent();
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    glClearColor(0.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glEnable(GL_CULL_FACE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE);
+
+	Q_ASSERT(NULL!=m_projectorData);
+    m_projectorData->beginDraw();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+    Matrix44f invProjTransMat = m_projectorTransformMatrix.getMatrix();
+    invert(invProjTransMat);
+	glMultMatrixf(invProjTransMat.getData());
+
+    switch (drawMode)
+    {
+    case CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP:
+        m_pModel->getScreen()->drawFrame();
+        for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+        {
+            if (m_pModel->getChannel(i)->getProjector()->getShowArea())
+                m_pModel->getScreen()->draw(PROJECT_SOURCE_PROJECTORAREA, m_pModel->getChannel(i));
+        }
+        if (getShowProjectedScene())
+            m_pModel->getScreen()->draw(PROJECT_SOURCE_SCENE, this);
+        break;
+    case CHANNEL_DRAWMODE_EXPORT_DISTORTIONMAP:
+        m_pModel->getScreen()->draw(PROJECT_SOURCE_EXPORT_DISTORTION, this);
+        m_pModel->getScreen()->draw(PROJECT_SOURCE_EXPORT_DISTORTION_R, this);
+        break;
+    case CHANNEL_DRAWMODE_DESIGN_BLENDMAP:
+    case CHANNEL_DRAWMODE_EXPORT_BLENDMAP:
+        {
+            float blendFactor = getBlendFactor(m_name);
+            glColor4f(blendFactor, blendFactor, blendFactor, 1.0f);
+
+            glBlendFunc(GL_ONE, GL_ONE);
+            m_pModel->getScreen()->draw(PROJECT_SOURCE_EXPORT_BLENDING, this);
+
+            for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+            {
+                if (m_pModel->getChannel(i) != this) {
+                    float blendFactor = getBlendFactor(m_pModel->getChannel(i)->getName());
+                    glColor4f(blendFactor, blendFactor, blendFactor, 1.0f);
+                    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+                    m_pModel->getScreen()->draw(PROJECT_SOURCE_EXPORT_BLENDING, m_pModel->getChannel(i));
+                }
+            }
+        }
+        break;
+    }
+
+    glPopMatrix();
+
+    glPopAttrib();
+
+    if (m_pDistWarp->getEnabled() ||
+        drawMode == CHANNEL_DRAWMODE_DESIGN_BLENDMAP ||
+        drawMode == CHANNEL_DRAWMODE_EXPORT_BLENDMAP)
+    {
+#if defined(Q_WS_X11)
+        // rendering directly to a texture is not supported on X11, unfortunately
+        getWarpBuffer()->updateDynamicTexture(m_warpTextureID);
+#endif
+
+        // finish off-screen rendering, then apply it as a texture to warping mesh.
+        m_pModel->activateRenderContext();
+
+ #if  defined(Q_WS_X11)
+        // rendering directly to a texture is not supported on X11, unfortunately
+        getWarpBuffer()->updateDynamicTexture(m_warpTextureID);
+ #endif
+
+        glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+        glBindTexture(GL_TEXTURE_2D, m_warpTextureID);
+
+        if (drawMode == CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP)
+            glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+        else
+            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        switch (drawMode)
+        {
+        case CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            m_pDistWarp->draw(false, false);
+            break;
+        case CHANNEL_DRAWMODE_EXPORT_DISTORTIONMAP:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            m_pDistWarp->draw(true, false);
+            break;
+        case CHANNEL_DRAWMODE_DESIGN_BLENDMAP:
+        case CHANNEL_DRAWMODE_EXPORT_BLENDMAP:
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            m_pBlendWarp->draw(drawMode == CHANNEL_DRAWMODE_EXPORT_BLENDMAP, true);
+            break;
+        }
+        glPopAttrib();
+
+        glFlush();
+    }
+
+    // draw the overlay image
+    if (drawMode == CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP)
+    {
+		// overlayImageFile is set but Texture does not exist yet: create Texture
+        if (!m_overlayImageFileName.isEmpty() && m_overlayImageTexIndex == 0)
+        {
+            QPixmap overlayImage(m_overlayImageFileName);
+            if (!overlayImage.isNull())
+            {
+                m_overlayImageTexIndex = m_pModel->getGUI()->getGLWidget()->bindTexture(overlayImage, GL_TEXTURE_RECTANGLE_ARB);
+                m_overlayImageWidth = overlayImage.width();
+                m_overlayImageHeight = overlayImage.height();
+                glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
+                glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
+                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            }
+        }
+		// If Texture exists already: use it :)
+        if (m_overlayImageTexIndex != 0)
+        {
+            glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+            glMatrixMode(GL_PROJECTION);
+            glLoadIdentity();
+            glOrtho(0, 1, 1, 0, -1, 1);
+
+            glMatrixMode(GL_MODELVIEW);
+            glPushMatrix();
+            glLoadIdentity();
+
+            glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_ONE, GL_ONE);
+            glEnable(GL_TEXTURE_RECTANGLE_ARB);
+            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_overlayImageTexIndex);
+
+            glBegin(GL_QUADS);
+            glTexCoord2d(0, m_overlayImageHeight); glVertex3d(0.0, 0.0, 0.0);
+            glTexCoord2d(m_overlayImageWidth, m_overlayImageHeight); glVertex3d(1.0, 0.0, 0.0);
+            glTexCoord2d(m_overlayImageWidth, 0); glVertex3d(1.0, 1.0, 0.0);
+            glTexCoord2d(0, 0); glVertex3d(0.0, 1.0, 0.0);
+            glEnd();
+
+            glPopMatrix();
+
+            glPopAttrib();
+        }
+    }
+
+    glFlush();
+}
+
+/**
+ * Draw projector and view frustum shape objects.
+ *
+ * @param bSelected True to draw with selection highlight.
+ */
+void Channel::drawFrustums(bool bSelected)
+{
+	if (m_projectorData) 
+	{
+		m_projectorData->setVisibleFar(m_pModel->getScreen()->getSize() * 1.1);
+		glPushMatrix();
+		glMultMatrixf(m_projectorTransformMatrix.getMatrix().getData());
+		m_projectorData->draw(bSelected);
+		glPopMatrix();
+	}
+
+	m_view.setVisibleFar(m_pModel->getScreen()->getSize() * 1.1);
+	m_view.draw();
+}
+
+/**
+ * Set channel name.
+ *
+ * @param name Name of the channel.
+ */
+void Channel::setName(const QString& name)
+{
+    m_name = m_pModel->getUniqueName(name, this);
+
+    m_pModel->getGUI()->updateChannelNamesGUI();
+
+    updateData();
+}
+
+/**
+ * Retrieve name of the channel.
+ *
+ * @return Name of the channel.
+ */
+QString Channel::getName() const
+{
+    return m_name;
+}
+
+/**
+ * Show or hide the name of the channel in the projector view.
+ *
+ * @param bShow True to show the name of the channel, false to hide.
+ */
+void Channel::setOverlayName(bool bShow)
+{
+    m_bOverlayName = bShow;
+    updateData();
+}
+
+/**
+ * Check whether the name of the channel is shown or not.
+ *
+ * @return True if the name of the channel.
+ */
+bool Channel::getOverlayName() const
+{
+    return m_bOverlayName;
+}
+
+/**
+ * Set host name of the remote host PC to show this channel.
+ *
+ * @param hostName Host name of the remote host PC.
+ */
+void Channel::setRemoteHostName(const QString& hostName)
+{
+    m_remoteHostName = hostName;
+    updateData();
+}
+
+/**
+ * Retrieve host name of the remote host PC to show this channel.
+ *
+ * @return Host name of the remote host PC.
+ */
+QString Channel::getRemoteHostName() const
+{
+    return m_remoteHostName;
+}
+
+/**
+ * Enable or disable the full-screen mode at remote host PC.
+ *
+ * @param bFullScreen True to display this channel in full-screen mode at remote host PC.
+ */
+void Channel::setRemoteFullScreen(bool bFullScreen)
+{
+    m_bRemoteFullScreen = bFullScreen;
+    updateData();
+}
+
+/**
+ * Check whether this channel is full-screen or not at remote host PC.
+ *
+ * @return True to display this channel in full-screen mode at remote host PC.
+ */
+bool Channel::getRemoteFullScreen() const
+{
+    return m_bRemoteFullScreen;
+}
+
+/**
+ * Screen index for multi-monitor remote host PC.
+ *
+ * @param screenIndex Screen index to display this channel.
+ */
+void Channel::setRemoteScreen(int screen)
+{
+    m_remoteScreen = screen;
+    updateData();
+}
+
+/**
+ * Retrieve screen index for multi-monitor remote host PC.
+ *
+ * @return Screen index to display this channel.
+ */
+int Channel::getRemoteScreen() const
+{
+    return m_remoteScreen;
+}
+
+
+/**
+ * Set file name of image to overlay in the projection window.
+ *
+ * @param fileName File name to overlay in the projection window
+ */
+void Channel::setOverlayImageFileName(const QString& fileName)
+{
+	if (m_overlayImageFileName != fileName)	// If new File: proceed...
+    {
+		// Delete old Texture if set: (new texture will be created on next usage in draw() )
+		if (glIsTexture(m_overlayImageTexIndex))
+		{
+            glDeleteTextures(1, &m_overlayImageTexIndex);
+		}
+
+		// Set Index to Zero
+		m_overlayImageTexIndex = 0;
+
+		// Set new filename
+		m_overlayImageFileName = fileName;
+    }
+}
+
+/**
+ * Retrieve file name of image to overlay in the projection window.
+ *
+ * @return File name to overlay in the projection window
+ */
+QString Channel::getOverlayImageFileName() const
+{
+    return m_overlayImageFileName;
+}
+
+/**
+ * Retrieve projector frustum object.
+ *
+ * @return Projector frustum object.
+ */
+ProjectorData* Channel::getProjector()
+{
+		return m_projectorData;
+}
+
+/**
+ * Retrieve view frustum object.
+ *
+ * @return View frustum object.
+ */
+Frustum* Channel::getView()
+{
+    return &m_view;
+}
+
+/**
+ * Show or hide the projected scene in DesignView.
+ *
+ * @param bShow True to display the projected scene in DesignView.
+ */
+void Channel::setShowProjectedScene(bool bShow)
+{
+    m_bShowProjectedScene = bShow;
+    updateData();
+}
+
+/**
+ * Check whether the projected scene is shown in DesignView.
+ *
+ * @return True if the projected scene is shown in DesignView.
+ */
+bool Channel::getShowProjectedScene() const
+{
+    return m_bShowProjectedScene;
+}
+
+/**
+ * Show projector window of this channel.
+ */
+void Channel::showProjectorWindow()
+{
+    if (!m_pModel->getRSync()->isServer() &&
+        m_pModel->getRSync()->getHostName().toLower() != m_remoteHostName.toLower())
+        return;
+
+    m_pModel->getGUI()->showProjectorWindow(this);
+}
+
+/**
+ * Fit the view frustum to projection area on the screen surface.
+ *
+ * @return True if successfully fitted.
+ */
+bool Channel::fitView()
+{
+    return false;
+}
+
+/**
+ * Retrieve the rendered view texture object ID.
+ *
+ * @return Rendered view texture object ID.
+ */
+unsigned int Channel::getViewTexture()
+{
+    if (!m_pSceneBuffer)
+        renderSceneToViewBuffer();
+    return m_sceneTextureID;
+}
+
+/**
+ * Reconstruct the off-screen buffer for rendering the scene.
+ */
+void Channel::reconstructBuffer()
+{
+    if (m_pSceneBuffer)
+    {
+        m_pSceneBuffer->releaseFromDynamicTexture();
+        glDeleteTextures(1, &m_sceneTextureID);
+        delete m_pSceneBuffer;
+    }
+    m_pSceneBuffer = NULL;
+}
+
+/**
+ * Retrieve distortion map warping class instance.
+ *
+ * @return Distortion map warping class instance.
+ */
+Warp* Channel::getDistWarp() const
+{
+    return m_pDistWarp;
+}
+
+/**
+ * Retrieve blend map warping class instance.
+ *
+ * @return Blend map warping class instance.
+ */
+Warp* Channel::getBlendWarp() const
+{
+    return m_pBlendWarp;
+}
+
+/**
+ * Retrieve the current (distortion / blend map) warp class instance.
+ *
+ * @return Current (distortion / blend map) warp class instance.
+ */
+Warp* Channel::getCurrentWarp() const
+{
+    if (m_pModel->getDesignMode() == DESIGN_MODE_DISTORTIONMAP)
+        return m_pDistWarp;
+    return m_pBlendWarp;
+}
+
+/**
+ * Enable or disable distortion map warping.
+ *
+ * @param bEnabled True to enable the distortion map warping, false to disable.
+ */
+void Channel::setDistWarpEnabled(bool bEnabled)
+{
+    m_pDistWarp->setEnabled(bEnabled);
+    if (!bEnabled)
+        clearWarpBuffer();
+    updateData();
+}
+
+/**
+ * Check whether the distortion map warping is enabled or not.
+ *
+ * @return True if the distortion map warping is enabled.
+ */
+bool Channel::getDistWarpEnabled() const
+{
+    return m_pDistWarp->getEnabled();
+}
+
+/**
+ * Retrieve (or create if not exist) off-screen buffer object for warping.
+ *
+ * @return Off-screen buffer object for warping.
+ */
+QGLPixelBuffer* Channel::getWarpBuffer()
+{
+    if (!m_pWarpBuffer)
+    {
+        m_pWarpBuffer = new QGLPixelBuffer(1024, 1024, QGLFormat::defaultFormat(), m_pModel->getGUI()->getGLWidget());
+        m_pModel->activateRenderContext();
+        m_warpTextureID = m_pWarpBuffer->generateDynamicTexture();
+        m_pWarpBuffer->bindToDynamicTexture(m_warpTextureID);
+        m_pModel->activateRenderContext();
+    }
+    return m_pWarpBuffer;
+}
+
+/**
+ * Discard the off-screen buffer object for warping.
+ */
+void Channel::clearWarpBuffer()
+{
+    if (m_pWarpBuffer)
+    {
+        m_pWarpBuffer->releaseFromDynamicTexture();
+        glDeleteTextures(1, &m_warpTextureID);
+        delete m_pWarpBuffer;
+        m_pWarpBuffer = NULL;
+    }
+}
+
+/**
+ * Set blending factor of the specified channel for exporting a blend map.
+ *
+ * @param name Name of channel to set blending factor.
+ * @param factor Blending factor (0.0-1.0).
+ */
+void Channel::setBlendFactor(const QString& name, float factor)
+{
+    m_blendFactors[name] = factor;
+    if (m_pModel->getRSync()->isServer())
+    {
+        QDomDocument doc;
+        doc.appendChild(domElement("Channel", doc));
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_CHANNEL, doc.toString(0));
+    }
+}
+
+/**
+ * Retrieve the blending factor of the specified channel.
+ *
+ * @param name Name of channel to retrieve the blending factor.
+ * @return Blending factor of the specified channel.
+ */
+float Channel::getBlendFactor(const QString& name) const
+{
+    if (m_blendFactors.contains(name))
+        return m_blendFactors.value(name);
+    if (name == m_name)
+        return 1.0f;
+    return 0.0f;
+}
+
+/**
+ * Export projection settings to file.
+ *
+ * @param fileName File name of the projection settings to save.
+ * @return True if successfully exported.
+ */
+bool Channel::exportDataset(const QString& fileName)
+{
+    if (fileName.isEmpty())
+        return false;
+
+    QFileInfo fileInfo(fileName);
+
+    QString exportFileName;
+
+    // export to a distortion map file
+    QGLPixelBuffer rttBufferDist(m_pModel->getExporter()->getExportWidth(), m_pModel->getExporter()->getExportHeight(),
+                                 QGLFormat::defaultFormat(), m_pModel->getGUI()->getGLWidget());
+    rttBufferDist.makeCurrent();
+    m_pModel->setRenderContext(&rttBufferDist);
+    draw(CHANNEL_DRAWMODE_EXPORT_DISTORTIONMAP);
+    rttBufferDist.doneCurrent();
+    exportFileName = replaceKeywordInFileName(QString("%1/%2").arg(fileInfo.absolutePath()).arg(m_pModel->getExporter()->getDistortMapFileNamePattern()));
+    rttBufferDist.toImage().save(exportFileName.toLocal8Bit());
+
+    // export to a blend map file
+    QGLPixelBuffer rttBufferBlend(m_pModel->getExporter()->getExportWidth(), m_pModel->getExporter()->getExportHeight(),
+                                  QGLFormat::defaultFormat(), m_pModel->getGUI()->getGLWidget());
+    rttBufferBlend.makeCurrent();
+    m_pModel->setRenderContext(&rttBufferBlend);
+    draw(CHANNEL_DRAWMODE_EXPORT_BLENDMAP);
+    rttBufferBlend.doneCurrent();
+    exportFileName = replaceKeywordInFileName(QString("%1/%2").arg(fileInfo.absolutePath()).arg(m_pModel->getExporter()->getBlendMapFileNamePattern()));
+    {
+        // get rid of the alpha channel.
+        QByteArray byteArray;
+        QBuffer buffer(&byteArray);
+        buffer.open(QIODevice::ReadWrite);
+        rttBufferBlend.toImage().save(&buffer, "bmp");
+        QImage image = QImage::fromData(byteArray, "bmp");
+        image.save(exportFileName.toLocal8Bit());
+    }
+
+    // export to a camera matrix file
+    exportFileName = replaceKeywordInFileName(QString("%1/%2").arg(fileInfo.absolutePath()).arg(m_pModel->getExporter()->getViewMatrixFileNamePattern()));
+    FILE* fp = fopen(exportFileName.toLocal8Bit(), "w");
+    if (fp) {
+        QString configData;
+        configData = QString("Camera \"%1\"\n{\n").arg(getName());
+        configData += QString("    Lens {\n%1\n    }\n").arg(m_view.getProjectionMatrix().getParams(8));
+        configData += QString("    Offset {\n%1    }\n").arg(m_view.getTransformMatrix().getParams(8));
+        configData += QString("}\n");
+
+        fprintf(fp, configData.toStdString().c_str());
+        fclose(fp);
+    }
+
+    clearWarpBuffer();
+
+    return true;
+}
+
+/**
+ * Replace pre-defined keyword in file name pattern.
+ *
+ * @param pattern File name pattern.
+ * @return File name pattern whose keywords replaced.
+ */
+QString Channel::replaceKeywordInFileName(const QString& pattern)
+{
+    QString result = pattern;
+    result = result.replace(QString("%CHANNELNAME%"), m_name);
+    result = result.replace(QString("%CHANNELINDEX%"), QString::number(m_pModel->getChannelIndex(this)));
+    result = result.replace(QString("%REMOTEHOST%"), m_remoteHostName);
+    return result;
+}
+
+/**
+ * Assignment operator.
+ *
+ * @param chan Assignment source channel.
+ */
+Channel& Channel::operator=(const Channel& chan)
+{
+    if (this != &chan)
+    {
+        m_bOverlayName = chan.m_bOverlayName;
+        m_overlayImageFileName = chan.m_overlayImageFileName;
+        m_bShowProjectedScene = chan.m_bShowProjectedScene;
+        m_bRemoteFullScreen = chan.m_bRemoteFullScreen;
+        m_remoteScreen = chan.m_remoteScreen;
+        m_view = chan.m_view;
+        QDomDocument doc;
+        m_pDistWarp->initFromDOMElement(chan.m_pDistWarp->domElement("DistMapWarp", doc));
+        m_pBlendWarp->initFromDOMElement(chan.m_pBlendWarp->domElement("BlendMapWarp", doc));
+		if (chan.m_projectorData)
+		{
+				m_projectorData = chan.m_projectorData->plugin()->newProjectorData(chan.m_projectorData->projector());
+				m_projectorData->copy_from(*chan.m_projectorData);
+		}
+		else
+				m_projectorData = NULL;
+		m_projectorTransformMatrix = chan.m_projectorTransformMatrix;
+    }
+    return *this;
+}
+
+/**
+ * Restore the channel data from XML data.
+ *
+ * @param element Parent XML element of the channel data.
+ */
+bool Channel::initFromDOMElement(const QDomElement& element, const QString& version)
+{
+    if (!element.isNull())
+    {
+        m_name = element.attribute("name");
+        m_bOverlayName = (element.attribute("overlayName")=="true");
+        m_overlayImageFileName = element.attribute("overlayImageFileName");
+        m_bShowProjectedScene = element.attribute("showProjectedScene")=="true"?true:false;
+        m_remoteHostName = element.attribute("remoteHostName");
+        m_bRemoteFullScreen = element.attribute("remoteFullScreen")=="true"?true:false;
+        m_remoteScreen = element.attribute("remoteScreen").toInt();
+        if (!element.firstChildElement("DistMapWarp").isNull())
+            m_pDistWarp->initFromDOMElement(element.firstChildElement("DistMapWarp"));
+    if (!element.firstChildElement("Warp").isNull())
+        m_pDistWarp->initFromDOMElement(element.firstChildElement("Warp"));
+        m_pBlendWarp->initFromDOMElement(element.firstChildElement("BlendMapWarp"));
+        m_blendFactors.clear();
+        QDomElement blend = element.firstChildElement("Blend");
+        if (!blend.isNull()) {
+            QDomElement factor = blend.firstChildElement("factor");
+            while (!factor.isNull()) {
+                m_blendFactors[factor.attribute("channel")] = factor.attribute("value").toFloat();
+                factor = factor.nextSiblingElement("factor");
+            }
+        }
+
+				// Compatibility conversion
+				QDomElement projectorDataElement, projectorTransformMatrixElement;
+				if (version_lt(version, "1.0.99.plugin"))
+				{
+						// Dom Element Conversion, from 1.0.0 to 1.0.99.plugin version
+
+						/* .
+							 . domElement_v1.0.0
+							 . `-- Channel
+							 .     `-- Projector {showArea, show}
+							 .        |-- ProjectionMatrix {far, fov, near, offaxisX, offaxisY, aspectRatio}
+							 .        `-- TransformMatrix
+							 .           |-- position {x, y, z}
+							 .           |-- rotation {h, p, r}
+							 .           `-- scaling {x, y, z}
+							 .
+							 . domElement_v1.0.99.plugin
+							 . `-- Channel
+							 .     |-- projectorTransformMatrix
+							 .     |  |-- position {x=domElement_v1.0.0->Channel->Projector->TransformMatrix->position->x, y=domElement_v1.0.0->Channel->Projector->TransformMatrix->position->y, z=domElement_v1.0.0->Channel->Projector->TransformMatrix->position->z}
+							 .     |  |-- rotation {h=domElement_v1.0.0->Channel->Projector->TransformMatrix->rotation->h, p=domElement_v1.0.0->Channel->Projector->TransformMatrix->rotation->p, r=domElement_v1.0.0->Channel->Projector->TransformMatrix->rotation->r}
+							 .     |  `-- scaling {x=domElement_v1.0.0->Channel->Projector->TransformMatrix->scale->x, y=domElement_v1.0.0->Channel->Projector->TransformMatrix->scale->y, z=domElement_v1.0.0->Channel->Projector->TransformMatrix->scale->z}
+							 .     `-- projectorData {far=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->far, pluginName="Standard Frustum", visibleFar=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->visibleFar, fov=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->fov, near=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->near, showArea=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->showArea, offaxisX=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->offaxisX, show=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->show, offaxisY=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->offaxisY, aspectRatio=domElement_v1.0.0->Channel->Projector->ProjectionMatrix->aspectRatio}
+							 . 
+						*/
+
+						qDebug()<<"Channel.cpp : 1.0.0->1.0.99 parameters import";
+						QDomElement v1_0_0_Projector = element.firstChildElement("Projector");
+						QDomElement v1_0_0_ProjectorProjectionMatrix = v1_0_0_Projector.firstChildElement("ProjectionMatrix");
+						QDomElement v1_0_0_ProjectorTransformMatrixPosition = v1_0_0_Projector.firstChildElement("TransformMatrix").firstChildElement("position");
+						QDomElement v1_0_0_ProjectorTransformMatrixRotation = v1_0_0_Projector.firstChildElement("TransformMatrix").firstChildElement("rotation");
+
+						projectorTransformMatrixElement = element.ownerDocument().createElement("projectorTransformMatrix");
+
+						QDomElement positionElement;
+						positionElement = element.ownerDocument().createElement("position");
+            positionElement.setAttribute("x", v1_0_0_ProjectorTransformMatrixPosition.attribute("x"));
+            positionElement.setAttribute("y", v1_0_0_ProjectorTransformMatrixPosition.attribute("y"));
+            positionElement.setAttribute("z", v1_0_0_ProjectorTransformMatrixPosition.attribute("z"));
+            projectorTransformMatrixElement.appendChild(positionElement);
+
+						QDomElement rotationElement;
+						rotationElement = element.ownerDocument().createElement("rotation");
+            rotationElement.setAttribute("h", v1_0_0_ProjectorTransformMatrixRotation.attribute("h"));
+            rotationElement.setAttribute("p", v1_0_0_ProjectorTransformMatrixRotation.attribute("p"));
+            rotationElement.setAttribute("r", v1_0_0_ProjectorTransformMatrixRotation.attribute("r"));
+            projectorTransformMatrixElement.appendChild(rotationElement);
+
+						projectorDataElement = element.ownerDocument().createElement("projectorData");
+
+						projectorDataElement.setAttribute("pluginName", "Standard Frustum");
+						projectorDataElement.setAttribute("showArea",    v1_0_0_Projector.attribute("showArea"));
+						projectorDataElement.setAttribute("show",        v1_0_0_Projector.attribute("show"));
+						projectorDataElement.setAttribute("far",         v1_0_0_ProjectorProjectionMatrix.attribute("far"));
+						projectorDataElement.setAttribute("visibleFar",  v1_0_0_ProjectorProjectionMatrix.attribute("visibleFar"));
+						projectorDataElement.setAttribute("fov",         v1_0_0_ProjectorProjectionMatrix.attribute("fov"));
+						projectorDataElement.setAttribute("near",        v1_0_0_ProjectorProjectionMatrix.attribute("near"));
+						projectorDataElement.setAttribute("offaxisX",    v1_0_0_ProjectorProjectionMatrix.attribute("offaxisX"));
+						projectorDataElement.setAttribute("offaxisY",    v1_0_0_ProjectorProjectionMatrix.attribute("offaxisY"));
+						projectorDataElement.setAttribute("aspectRatio", v1_0_0_ProjectorProjectionMatrix.attribute("aspectRatio"));
+				}
+				else
+				{
+						projectorDataElement=element.firstChildElement("projectorData");
+						projectorTransformMatrixElement=element.firstChildElement("projectorTransformMatrix");
+				}
+
+				if (!projectorDataElement.isNull())
+				{
+						QString projector_fullname = projectorDataElement.attribute("projectorFullName");
+						setProjector (projector_fullname);
+						Q_ASSERT(NULL!=m_projectorData);
+						m_projectorData->initFromDOMElement(projectorDataElement);
+				}
+				m_projectorTransformMatrix.initFromDOMElement(projectorTransformMatrixElement);
+        m_view.initFromDOMElement(element.firstChildElement("View"));
+
+        if (!m_pModel->getRSync()->isServer() &&
+            m_pModel->getRSync()->getHostName().toLower() == m_remoteHostName.toLower())
+        {
+            showProjectorWindow();
+        }
+    }
+
+    updateData();
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current channel data as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current channel data as XML data.
+ */
+QDomElement Channel::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.setAttribute("name", m_name);
+    de.setAttribute("overlayName", m_bOverlayName?"true":"false");
+    de.setAttribute("overlayImageFileName", m_overlayImageFileName);
+    de.setAttribute("showProjectedScene", m_bShowProjectedScene?"true":"false");
+    de.setAttribute("remoteHostName", m_remoteHostName);
+    de.setAttribute("remoteFullScreen", m_bRemoteFullScreen?"true":"false");
+    de.setAttribute("remoteScreen", QString::number(m_remoteScreen));
+
+    de.appendChild(m_pDistWarp->domElement("DistMapWarp", doc));
+    de.appendChild(m_pBlendWarp->domElement("BlendMapWarp", doc));
+
+    QDomElement blend = doc.createElement("Blend");
+    QMapIterator<QString, float> iter(m_blendFactors);
+    while (iter.hasNext()) {
+        iter.next();
+        if (m_pModel->hasChannel(iter.key())) {
+            QDomElement factor = doc.createElement("factor");
+            factor.setAttribute("channel", iter.key());
+            factor.setAttribute("value", QString::number(iter.value()));
+            blend.appendChild(factor);
+        }
+    }
+    de.appendChild(blend);
+
+		Q_ASSERT(NULL!=m_projectorData);
+		QDomElement plugin_data = m_projectorData->domElement("projectorData", doc);
+		plugin_data.setAttribute("projectorFullName", m_projectorData->getFullName());
+
+		de.appendChild(m_projectorTransformMatrix.domElement("projectorTransformMatrix", doc));
+
+		de.appendChild(plugin_data);
+
+		de.appendChild(m_view.domElement("View", doc));
+
+    return de;
+}
+
+/**
+ * Called when channel, projector or view frustum is changed.
+ * Always render the scene to the off-screen buffer...
+ */
+void Channel::updateData()
+{
+    if (m_pModel->getRSync()->isServer())
+    {
+        QDomDocument doc;
+        doc.appendChild(domElement("Channel", doc));
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_CHANNEL, doc.toString(0));
+    }
+
+    m_pModel->getGUI()->updateChannelGUI();
+    if (m_bShowProjectedScene)
+        m_pModel->updateViewAndOffscreens();
+    else
+        m_pModel->updateViews();
+}
+
+void Channel::setProjector(ProjectorInterface *projector_interface, const QString& projector_name)
+{
+		if (NULL==projector_interface)
+		{
+				projector_interface=ProjectionModel::projector_interfaces[0];
+		}
+
+		QString _projector_name=projector_name;
+		if (_projector_name=="")
+		{
+				_projector_name=projector_interface->projectors()[0];
+		}
+
+		// First case : There is no previous data.
+		if (!m_projectorData)
+		{
+				// New data allocated (through the plugin).
+				m_projectorData = projector_interface->newProjectorData(_projector_name);
+		}
+		// Second case : There was some previous data.
+		else
+		{
+				// First sub-case : The current plugin is different from the previous one.
+ 				if (projector_interface!=m_projectorData->plugin() || _projector_name!=m_projectorData->projector())
+ 				{
+						// Delete previous ones.
+						delete m_projectorData;
+						m_projectorData=NULL;
+
+						// New data allocated (through the plugin).
+						m_projectorData = projector_interface->newProjectorData(_projector_name);
+
+						Q_ASSERT(projector_interface==m_projectorData->plugin());
+ 				}
+				// Second sub-case : The plugin is always the same => Do Nothing.
+		}
+}
+
+void Channel::setProjector(const QString& projector_fullname)
+{
+		ProjectorInterface *projector_interface=NULL;
+		foreach (projector_interface, ProjectionModel::projector_interfaces)
+				{
+						foreach(QString projector_name, projector_interface->projectors())
+								{
+										QString _projector_fullname = projector_name;
+										_projector_fullname += " (";
+										_projector_fullname += projector_interface->name();
+										_projector_fullname += ")";
+										if (_projector_fullname == projector_fullname)
+										{
+												setProjector (projector_interface, projector_name);
+												return;
+										}
+								}
+				}
+		setProjector();
+}
+
+
+void Channel::setProjectorTransformMatrix(const TransformMatrix& matrix)
+{
+    m_projectorTransformMatrix = matrix;
+		updateData();
+}
+
+TransformMatrix& Channel::getProjectorTransformMatrix(void)
+{
+    return m_projectorTransformMatrix;
+}
+
+void Channel::setViewProjectionMatrix(const ProjectionMatrix& matrix)
+{
+		m_view.setProjectionMatrix(matrix);
+}
+
+void Channel::setViewTransformMatrix(const TransformMatrix& matrix)
+{
+		m_view.setTransformMatrix(matrix);
+}
+
+void Channel::updatePluginData(const ProjectorData& data)
+{
+		Q_ASSERT(m_projectorData->getFullName()==data.getFullName());
+		if (!data.is_equal_to(*m_projectorData))
+ 		{
+				m_projectorData->copy_from(data);
+				updateData();
+ 		}
+}
+
Index: projectionDesigner/trunk/projdesigner/src/Exporter.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Exporter.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Exporter.cpp	(revision 4)
@@ -0,0 +1,300 @@
+#include <QImage>
+#include <QGLWidget>
+#include <QPainter>
+#include "ProjectionModel.h"
+#include "Channel.h"
+#include "RSync.h"
+#include "GUIControler.h"
+
+#include "Exporter.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pModel Projection model.
+ */
+Exporter::Exporter(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+
+    m_bSoftEdge = true;
+    m_blendEdgeWidth = 16;
+    m_blendEdgeExponent = 1.0f;
+    m_exportWidth = 512;
+    m_exportHeight = 512;
+    m_distortMapFileNamePattern = "distort_%CHANNELNAME%.bmp";
+    m_blendMapFileNamePattern = "blend_%CHANNELNAME%.bmp";
+    m_viewMatrixFileNamePattern = "view_%CHANNELNAME%.cfg";
+
+    m_texCoordColorTexIndex = 0;
+    m_texCoordColorRTexIndex = 0;
+    m_blendAreaTexIndex = 0;
+}
+
+/**
+ * Destructor.
+ */
+Exporter::~Exporter()
+{
+    if (glIsTexture(m_texCoordColorTexIndex))
+        glDeleteTextures(1, &m_texCoordColorTexIndex);
+    if (glIsTexture(m_blendAreaTexIndex))
+        glDeleteTextures(1, &m_blendAreaTexIndex);
+}
+
+/**
+ * Enable or disable soft edge blending.
+ *
+ * @param bSoftEdge True if soft edge blending is enabled.
+ */
+void Exporter::setSoftEdge(bool bSoftEdge)
+{
+    if (m_bSoftEdge != bSoftEdge) {
+        m_bSoftEdge = bSoftEdge;
+        if (glIsTexture(m_blendAreaTexIndex))
+            glDeleteTextures(1, &m_blendAreaTexIndex);
+        m_blendAreaTexIndex = 0;
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Exporter", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORT, doc.toString(0));
+        }
+        if (m_pModel->getDesignMode() == DESIGN_MODE_BLENDMAP)
+            m_pModel->updateViews();
+    }
+}
+
+/**
+ * Set width of the soft edge blending.
+ *
+ * @param blendWidth Width of the soft edge blending.
+ */
+void Exporter::setBlendEdgeWidth(int blendEdgeWidth)
+{
+    if (m_blendEdgeWidth != blendEdgeWidth) {
+        m_blendEdgeWidth = blendEdgeWidth;
+        if (glIsTexture(m_blendAreaTexIndex))
+            glDeleteTextures(1, &m_blendAreaTexIndex);
+        m_blendAreaTexIndex = 0;
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Exporter", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORT, doc.toString(0));
+        }
+        if (m_pModel->getDesignMode() == DESIGN_MODE_BLENDMAP)
+            m_pModel->updateViews();
+    }
+}
+
+/**
+ * Set gamma curve of blend map edge.
+ *
+ * @param gamma Curve exponent of blend map edge.
+ */
+void Exporter::setBlendEdgeExponent(float blendEdgeExponent)
+{
+    if (m_blendEdgeExponent != blendEdgeExponent) {
+        m_blendEdgeExponent = blendEdgeExponent;
+        if (glIsTexture(m_blendAreaTexIndex))
+            glDeleteTextures(1, &m_blendAreaTexIndex);
+        m_blendAreaTexIndex = 0;
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Exporter", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORT, doc.toString(0));
+        }
+        if (m_pModel->getDesignMode() == DESIGN_MODE_BLENDMAP)
+            m_pModel->updateViews();
+    }
+}
+
+/**
+ * Set width of distortion map to export.
+ *
+ * @param width Width of distortion map to export.
+ */
+void Exporter::setExportWidth(int exportWidth)
+{
+    if (m_exportWidth != exportWidth) {
+        m_exportWidth = exportWidth;
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Exporter", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORT, doc.toString(0));
+        }
+    }
+}
+
+/**
+ * Set height of distortion map to export.
+ *
+ * @param height Height of distortion map to export.
+ */
+void Exporter::setExportHeight(int exportHeight)
+{
+    if (m_exportHeight != exportHeight) {
+        m_exportHeight = exportHeight;
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Exporter", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORT, doc.toString(0));
+        }
+    }
+}
+
+/**
+ * Create a color encoded coordinate texture and retrieve its texture object index.
+ *
+ * @return Texture object index of the encoded coordinate texture.
+ */
+unsigned int Exporter::getTexCoordColorTexture()
+{
+    if (m_texCoordColorTexIndex == 0)
+    {
+        unsigned char *data;
+        data = new unsigned char[256*256*4];
+        int count = 0;
+        for (unsigned int y=0; y<256; ++y) {
+            for (unsigned int x=0; x<256; ++x) {
+                data[x*4+y*256*4+0] = x;
+                data[x*4+y*256*4+1] = y;
+                data[x*4+y*256*4+2] = 0;
+                data[x*4+y*256*4+3] = 255;
+                count++;
+            }
+        }
+        QImage image((uchar *)data, 256, 256, QImage::Format_RGB32);
+        m_texCoordColorTexIndex = m_pModel->getGUI()->getGLWidget()->bindTexture(image);
+        delete [] data;
+    }
+    return m_texCoordColorTexIndex;
+}
+
+/**
+ * Create a color encoded coordinate texture (red channel) and retrieve its texture object index.
+ *
+ * @return Texture object index of the encoded coordinate texture (red channel).
+ */
+unsigned int Exporter::getTexCoordColorRTexture()
+{
+    if (m_texCoordColorRTexIndex == 0)
+    {
+        unsigned char* data;
+        data = new unsigned char[16*16*4];
+        int count = 0;
+        for (unsigned int y=0; y<16; ++y) {
+            for (unsigned int x=0; x<16; ++x) {
+                data[x*4+y*16*4+0] = 0;
+                data[x*4+y*16*4+1] = 0;
+                data[x*4+y*16*4+2] = x+y*16;
+                data[x*4+y*16*4+3] = 255;
+                count++;
+            }
+        }
+        QImage image((uchar *)data, 16, 16, QImage::Format_RGB32);
+        m_texCoordColorRTexIndex = m_pModel->getGUI()->getGLWidget()->bindTexture(image);
+        delete [] data;
+    }
+    return m_texCoordColorRTexIndex;
+}
+/**
+ * Create an edge blending texture and retrieve its texture object index.
+ *
+ * @return Texture object index of the edge blending texture.
+ */
+unsigned int Exporter::getBlendingAreaTexture()
+{
+    if (m_blendAreaTexIndex == 0)
+    {
+        int blendBaseValue = 255;
+        QPixmap pixmap(128, 128);
+        pixmap.fill(QColor(blendBaseValue, blendBaseValue, blendBaseValue));
+        if (m_bSoftEdge)
+        {
+            QPainter painter(&pixmap);
+            QPen pen;
+            for (int w=0; w<m_blendEdgeWidth; w++) {
+			    int value = int(pow(1.0f/m_blendEdgeWidth*(m_blendEdgeWidth-w-1), m_blendEdgeExponent) * blendBaseValue);
+                pen.setColor(QColor(value, value, value));
+                pen.setWidth(m_blendEdgeWidth-w);
+                painter.setPen(pen);
+                painter.drawRect(0, 0, 127, 127);
+            }
+        }
+        m_blendAreaTexIndex = m_pModel->getGUI()->getGLWidget()->bindTexture(pixmap);
+    }
+    return m_blendAreaTexIndex;
+}
+
+/**
+ * Export projection settings to file.
+ *
+ * @param fileName File name of the projection settings.
+ * @return True if successfully exported.
+ */
+bool Exporter::exportDataset(const QString& fileName)
+{
+	for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+        m_pModel->getChannel(i)->exportDataset(fileName);
+    if (m_pModel->getRSync()->isServer())
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_EXPORTFILE, fileName);
+
+    return true;
+}
+
+/**
+ * Restore the export settings from XML data.
+ *
+ * @param element Parent XML element of the export settings data.
+ */
+bool Exporter::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        setSoftEdge(element.attribute("softEdge")=="true");
+        setBlendEdgeWidth(element.attribute("blendEdgeWidth").toInt());
+        setBlendEdgeExponent(element.attribute("blendEdgeExponent").toFloat());
+        m_exportWidth = element.attribute("exportWidth").toInt();
+        m_exportHeight = element.attribute("exportHeight").toInt();
+        m_distortMapFileNamePattern = element.attribute("distortMapFileNamePattern");
+        m_blendMapFileNamePattern = element.attribute("blendMapFileNamePattern");
+        m_viewMatrixFileNamePattern = element.attribute("viewMatrixFileNamePattern");
+        if (m_distortMapFileNamePattern.isEmpty())
+            m_distortMapFileNamePattern = "distort_%CHANNELNAME%.bmp";
+        if (m_blendMapFileNamePattern.isEmpty())
+            m_blendMapFileNamePattern = "blend_%CHANNELNAME%.bmp";
+        if (m_viewMatrixFileNamePattern.isEmpty())
+            m_viewMatrixFileNamePattern = "view_%CHANNELNAME%.cfg";
+    }
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current export settings as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current export settings data as XML data.
+ */
+QDomElement Exporter::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.setAttribute("softEdge", m_bSoftEdge?"true":"false");
+    de.setAttribute("blendEdgeWidth", QString::number(m_blendEdgeWidth));
+    de.setAttribute("blendEdgeExponent", QString::number(m_blendEdgeExponent));
+    de.setAttribute("exportWidth", QString::number(m_exportWidth));
+    de.setAttribute("exportHeight", QString::number(m_exportHeight));
+    de.setAttribute("distortMapFileNamePattern", m_distortMapFileNamePattern);
+    de.setAttribute("blendMapFileNamePattern", m_blendMapFileNamePattern);
+    de.setAttribute("viewMatrixFileNamePattern", m_viewMatrixFileNamePattern);
+
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/Frustum.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Frustum.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Frustum.cpp	(revision 4)
@@ -0,0 +1,289 @@
+#include <QtOpenGL>
+
+#include "Frustum.h"
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor.
+ */
+Frustum::Frustum() : QObject()
+{
+    m_bShow = true;
+    m_bShowArea = true;
+    m_visibleFar = 1.2f;
+    m_color.setRgb(0, 0, 255);
+
+    m_transformMatrix.setUseScaling(false);
+}
+
+/**
+ * Destructor.
+ */
+Frustum::~Frustum()
+{
+}
+
+/**
+ * Set projection matrix of the frustum.
+ *
+ * @param matrix Projection matrix of the frustum.
+ */
+void Frustum::setProjectionMatrix(const ProjectionMatrix& matrix)
+{
+    m_projectionMatrix = matrix;
+    emit dataChanged();
+}
+
+/**
+ * Retrieve projection matrix of the frustum.
+ *
+ * @return Projection matrix of the frustum.
+ */
+ProjectionMatrix Frustum::getProjectionMatrix() const
+{
+    return m_projectionMatrix;
+}
+
+/**
+ * Set transform matrix of the frustum.
+ *
+ * @param matrix Transform matrix of the frustum.
+ */
+void Frustum::setTransformMatrix(const TransformMatrix& matrix)
+{
+    m_transformMatrix = matrix;
+    emit dataChanged();
+}
+
+/**
+ * Retrieve transform matrix of the frustum.
+ *
+ * @return Transform matrix of the frustum.
+ */
+TransformMatrix Frustum::getTransformMatrix() const
+{
+    return m_transformMatrix;
+}
+
+/**
+ * Set color of the frustum shape object.
+ *
+ * @param color Color of the frustum shape object.
+ */
+void Frustum::setColor(const QColor& color)
+{
+    m_color = color;
+    emit dataChanged();
+}
+
+/**
+ * Retrieve color of the frustum shape object.
+ *
+ * @return Color of the frustum shape object.
+ */
+QColor Frustum::getColor() const
+{
+    return m_color;
+}
+
+/**
+ * Show or hide the frustum shape object.
+ *
+ * @param bShow True to show the frustum shape object, false to hide.
+ */
+void Frustum::setShow(bool bShow)
+{
+    m_bShow = bShow;
+    emit dataChanged();
+}
+
+/**
+ * Check whether the frustum shape object is shown or not.
+ *
+ * @return True if the frustum shape object is shown.
+ */
+bool Frustum::getShow() const
+{
+    return m_bShow;
+}
+
+/**
+ * Show or hide the frustum projected area.
+ *
+ * @param bShow True to show the frustum projected area, false to hide.
+ */
+void Frustum::setShowArea(bool bShow)
+{
+    m_bShowArea = bShow;
+    emit dataChanged();
+}
+
+/**
+ * Check whether the frustum projected area is shown or not.
+ *
+ * @return True if the frustum projected area is shown.
+ */
+bool Frustum::getShowArea() const
+{
+    return m_bShowArea;
+}
+
+/**
+ * Set far clip plane distance of the frame shape object. It doesn't modify the  data.
+ *
+ * @param farDist Far clip plane distance of the frame shape object.
+ */
+void Frustum::setVisibleFar(float farDist)
+{
+    m_visibleFar = farDist;
+}
+
+/**
+ * Retrieve far clip plane distance of the frame shape object.
+ *
+ * @return Far clip plane distance of the frame shape object.
+ */
+float Frustum::getVisibleFar() const
+{
+    return m_visibleFar;
+}
+
+/**
+ * Draw frustum shape object.
+ *
+ * @param bSelected True to draw with selection highlight.
+ */
+void Frustum::draw(bool bSelected)
+{
+    if (m_bShow)
+    {
+        glPushMatrix();
+        glMultMatrixf(m_transformMatrix.getMatrix().getData());
+        glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LINE_BIT);
+
+        if (bSelected)
+            glLineWidth(3.0f);
+
+        float left =  -tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) * m_projectionMatrix.getAspectRatio() + m_projectionMatrix.getOffaxisX();
+        float right =  tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) * m_projectionMatrix.getAspectRatio() + m_projectionMatrix.getOffaxisX();
+        float top =   -tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) + m_projectionMatrix.getOffaxisY();
+        float bottom = tanf(Math::deg2Rad(m_projectionMatrix.getFOV()/2.0f)) + m_projectionMatrix.getOffaxisY();
+        float nearDist = m_projectionMatrix.getNear();
+        float farDist = m_projectionMatrix.getFar();
+        if (m_visibleFar < farDist)
+            farDist = m_visibleFar;
+
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        glDisable(GL_LIGHTING);
+
+        glBegin(GL_LINE_LOOP);
+        glVertex3f(nearDist*left,  nearDist*bottom, -nearDist);
+        glVertex3f(nearDist*right, nearDist*bottom, -nearDist);
+        glVertex3f(nearDist*right, nearDist*top,    -nearDist);
+        glVertex3f(nearDist*left,  nearDist*top,    -nearDist);
+        glEnd();
+        glBegin(GL_LINE_LOOP);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glVertex3f(farDist*left,  farDist*top,    -farDist);
+        glEnd();
+        glBegin(GL_LINES);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*top,    -farDist);
+        glEnd();
+
+        glColor4f((float)m_color.red()/255.0f, (float)m_color.green()/255.0f, (float)m_color.blue()/255.0f, 0.25f);
+        glEnable(GL_LIGHTING);
+        glEnable(GL_BLEND);
+        glDepthMask(false);
+
+        glBegin(GL_TRIANGLES);
+        glNormal3f(0.0f, cosf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f), -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glNormal3f( cosf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f),
+                    0.0f,
+                   -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glNormal3f(0.0f, -cosf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f), -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*top, -farDist);
+        glVertex3f(farDist*left,  farDist*top, -farDist);
+        glNormal3f(-cosf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f),
+                    0.0f,
+                   -sinf(Math::deg2Rad(m_projectionMatrix.getFOV())*m_projectionMatrix.getAspectRatio()/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left, farDist*top,    -farDist);
+        glVertex3f(farDist*left, farDist*bottom, -farDist);
+        glEnd();
+
+        glDepthMask(true);
+        glPopAttrib();
+        glPopMatrix();
+    }
+}
+
+/**
+ * Assignment operator.
+ *
+ * @param frustum Assignment source frustum.
+ */
+Frustum& Frustum::operator=(const Frustum& frustum)
+{
+    if (this != &frustum)
+    {
+        m_projectionMatrix = frustum.m_projectionMatrix;
+        m_transformMatrix = frustum.m_transformMatrix;
+        m_bShow = frustum.m_bShow;
+        m_visibleFar = frustum.m_visibleFar;
+        m_color = frustum.m_color;
+    }
+    return *this;
+}
+
+/**
+ * Restore the frustum data from XML data.
+ *
+ * @param element Parent XML element of the frustum data.
+ */
+void Frustum::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        m_projectionMatrix.initFromDOMElement(element.firstChildElement("ProjectionMatrix"));
+        m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix"));
+        m_bShow = element.attribute("show").toLower()=="true";
+        m_bShowArea = element.attribute("showArea").toLower()=="true";
+    }
+}
+
+/**
+ * Store the current frustum data as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current frustum data as XML data.
+ */
+QDomElement Frustum::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+
+    de.appendChild(m_projectionMatrix.domElement("ProjectionMatrix", doc));
+    de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc));
+    de.setAttribute("show", (m_bShow?"true":"false"));
+    de.setAttribute("showArea", (m_bShowArea?"true":"false"));
+
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/GUIControler.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/GUIControler.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/GUIControler.cpp	(revision 4)
@@ -0,0 +1,397 @@
+#include "ProjectionModel.h"
+#include "Channel.h"
+#include "RSync.h"
+#include "gui/QDesignViewWindow.h"
+#include "gui/QDesignViewWidget.h"
+#include "gui/QPanelWidget.h"
+#include "gui/QClientWindow.h"
+#include "gui/QProjectorWindow.h"
+#include "gui/QSceneViewerWindow.h"
+#include "gui/QPreferenceDialog.h"
+
+#include "GUIControler.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pModel Projection model.
+ */
+GUIControler::GUIControler(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+
+    m_pDesignViewWindow = NULL;
+    m_pClientWindow = NULL;
+    m_pSceneViewerWindow = NULL;
+    m_pPreferenceDialog = NULL;
+}
+
+/**
+ * Destructor.
+ */
+GUIControler::~GUIControler()
+{
+    delete m_pDesignViewWindow;
+    delete m_pClientWindow;
+}
+
+/**
+ * Initialize GUIs.
+ *
+ * @param bServer True if this program is a server, false if it is a client.
+ */
+void GUIControler::init(bool bServer)
+{
+    if (bServer)
+    {
+        m_pDesignViewWindow = new QDesignViewWindow;
+        m_pDesignViewWindow->setModel(m_pModel);
+        m_pDesignViewWindow->showMaximized();
+    }
+    else
+    {
+        m_pClientWindow = new QClientWindow(NULL);
+		m_pClientWindow->show();
+    }
+}
+
+/**
+ * Load projection settings from a file.
+ *
+ * @param fileName File name to load.
+ * @return True if successfully loaded.
+ */
+bool GUIControler::loadFile(const QString& fileName)
+{
+    if (m_pDesignViewWindow)
+        return m_pDesignViewWindow->loadFile(fileName);
+    return false;
+}
+
+/**
+ * Save the current projection settings to a file.
+ *
+ * @param fileName File name to save.
+ * @return True if successfully saved.
+ */
+bool GUIControler::saveFile(const QString& fileName)
+{
+    if (m_pDesignViewWindow)
+        return m_pDesignViewWindow->saveFile(fileName);
+    return false;
+}
+
+/**
+ * Retrieve main window.
+ *
+ * @return DesignViewWindow in server, ClientWindow in Client.
+ */
+QWidget* GUIControler::getMainWindow()
+{
+    if (m_pDesignViewWindow)
+        return m_pDesignViewWindow;
+    if (m_pClientWindow)
+        return m_pClientWindow;
+    return NULL;
+}
+
+/**
+ * Retrieve QGLWidget for sharing OpenGL context.
+ *
+ * @return QGLWidget for sharing OpenGL context.
+ */
+QGLWidget* GUIControler::getGLWidget()
+{
+    if (m_pDesignViewWindow) {
+        return m_pDesignViewWindow->getGLWidget();
+    }
+/*    else if (m_pProjectorWindows.size() > 0) {
+        return m_pProjectorWindows[0];
+    }*/
+    static QGLWidget* g_pGLWidget = NULL;
+    if (!g_pGLWidget)
+        g_pGLWidget = new QGLWidget(getMainWindow());
+    return g_pGLWidget;
+}
+
+/**
+ * Select a channel.
+ *
+ * @param pChannel Channel object to select.
+ */
+void GUIControler::selectChannel(Channel* pChannel)
+{
+    if (m_pDesignViewWindow) {
+        m_pDesignViewWindow->getPanel()->selectChannel(pChannel);
+    }
+}
+
+/**
+ * Remove the specified channel.
+ *
+ * @param pChannel Channel object to remove.
+ */
+void GUIControler::removeChannel(Channel* pChannel)
+{
+    for (int i=0; i<m_pProjectorWindows.size(); ++i) {
+        if (m_pProjectorWindows.at(i)->getChannel() == pChannel) {
+            QProjectorWindow* pProjectorWindow = m_pProjectorWindows.takeAt(i);
+            delete pProjectorWindow;
+            return;
+        }
+    }
+}
+
+/**
+ * Process key event for channel.
+ *
+ * @param pChannel Channel to process key event.
+ * @param pEvent Key event.
+ */
+void GUIControler::processChannelKeyEvent(Channel* pChannel, QKeyEvent* pEvent)
+{
+    m_pDesignViewWindow->getDesignView()->processChannelKeyEvent(pChannel, pEvent);
+}
+
+/**
+ * Update the channel list in GUI.
+ */
+void GUIControler::updateChannelsGUI()
+{
+    if (m_pDesignViewWindow)
+        m_pDesignViewWindow->getPanel()->updateChannels();
+}
+
+/**
+ * Update the name of channels in GUI.
+ */
+void GUIControler::updateChannelNamesGUI()
+{
+    if (m_pDesignViewWindow)
+        m_pDesignViewWindow->getPanel()->updateChannelNames();
+
+    for (int i=0; i<m_pProjectorWindows.size(); ++i)
+        m_pProjectorWindows[i]->updateTitle();
+}
+
+/**
+ * Update the channel in GUI.
+ */
+void GUIControler::updateChannelGUI()
+{
+    if (m_pDesignViewWindow)
+        m_pDesignViewWindow->getPanel()->updateCurrentChannel();
+}
+
+/**
+ * Update GUI.
+ */
+void GUIControler::updateGUI()
+{
+    if (m_pDesignViewWindow)
+        m_pDesignViewWindow->getPanel()->updateGUI();
+}
+
+/**
+ * Redraw SceneViewer.
+ */
+void GUIControler::updateSceneViewer()
+{
+    if (m_pSceneViewerWindow)
+    {
+        m_pSceneViewerWindow->blockSignals(true);
+        m_pSceneViewerWindow->updateGL();
+        m_pSceneViewerWindow->blockSignals(false);
+    }
+}
+
+/**
+ * Put the SceneViewer camera at the center of the scene.
+ */
+void GUIControler::sceneCenterView()
+{
+    if (m_pSceneViewerWindow)
+        m_pSceneViewerWindow->centerView();
+}
+
+/**
+ * Set the SceneViewer camera to view all the scene.
+ */
+void GUIControler::sceneViewAll()
+{
+    if (m_pSceneViewerWindow)
+        m_pSceneViewerWindow->viewAll();
+}
+
+/**
+ * Redraw DesignViewWindow and ProjectorWindows.
+ */
+void GUIControler::updateViews()
+{
+    if (m_pDesignViewWindow)
+        m_pDesignViewWindow->getDesignView()->updateGL();
+
+    for (int i=0; i<m_pProjectorWindows.size(); ++i)
+        if (m_pProjectorWindows[i]->isVisible())
+            m_pProjectorWindows[i]->updateGL();
+}
+
+/**
+ * Set scene size for SceneViewer.
+ *
+ * @param radius Radius of the scene.
+ */
+void GUIControler::setSceneSize(float radius)
+{
+    if (m_pSceneViewerWindow) {
+        m_pSceneViewerWindow->setSceneSize(radius * 4.0f);
+        m_pSceneViewerWindow->setZFar(radius * 4.0f);
+    }
+}
+
+/**
+ * Create (if not exist) and show a ProjectorWindow for the specified channel.
+ *
+ * @param pChannel Channel object for the ProjectorWindow.
+ */
+void GUIControler::showProjectorWindow(Channel* pChannel)
+{
+    if (!pChannel)
+        return;
+    QProjectorWindow* pProjectorWindow = NULL;
+    for (int i=0; i<m_pProjectorWindows.size(); ++i)
+        if (m_pProjectorWindows.at(i)->getChannel() == pChannel)
+            pProjectorWindow = m_pProjectorWindows[i];
+    if (!pProjectorWindow)
+    {
+        pProjectorWindow = new QProjectorWindow (0, getGLWidget(), Qt::Dialog);
+        pProjectorWindow->setModel(m_pModel);
+        pProjectorWindow->setChannel(pChannel);
+
+        m_pProjectorWindows.append(pProjectorWindow);
+    }
+
+    if (!m_pModel->getRSync()->isServer() && pChannel->getRemoteFullScreen())
+    {
+        QDesktopWidget desktop;
+        if (!pProjectorWindow->isFullScreen() ||
+            desktop.availableGeometry(pChannel->getRemoteScreen()) != desktop.availableGeometry(pProjectorWindow))
+        {
+            QRect rect = desktop.availableGeometry(pChannel->getRemoteScreen());
+            pProjectorWindow->move(rect.x() + 10, rect.y() + 10);
+            pProjectorWindow->showFullScreen();
+        }
+    } else
+        pProjectorWindow->showNormal();
+}
+
+/**
+ * Create (if not exist) and show a SceneViewerWindow.
+ */
+void GUIControler::showSceneViewerWindow()
+{
+    if (!m_pSceneViewerWindow)
+    {
+        m_pSceneViewerWindow = new QSceneViewerWindow(0);
+        m_pSceneViewerWindow->setModel(m_pModel);
+        m_pSceneViewerWindow->initFromDOMElement(m_sceneViewerSettings);
+    }
+    m_pSceneViewerWindow->show();
+}
+
+/**
+ * Create (if not exist) and show a PreferenceDialog.
+ */
+void GUIControler::showPreferenceDialog()
+{
+    if (!m_pPreferenceDialog)
+    {
+        m_pPreferenceDialog = new QPreferenceDialog(getMainWindow());
+        m_pPreferenceDialog->setModel(m_pModel);
+    }
+    m_pPreferenceDialog->show();
+}
+
+/**
+ * Show an instant message in status bar of the DesignViewWindow.
+ *
+ * @param message Message to show.
+ * @param timeout Time out interval to disappear in micro seconds.
+ */
+void GUIControler::showStatusBarMessage(const QString& message, int timeout)
+{
+    if (m_pDesignViewWindow)
+    m_pDesignViewWindow->statusBar()->showMessage(message, timeout);
+}
+
+/**
+ * Append log to Client Window.
+ *
+ * @param log Log text.
+ */
+void GUIControler::appendClientLog(const QString& log)
+{
+    if (m_pClientWindow)
+        m_pClientWindow->appendLog(log);
+}
+
+/**
+ * Close all windows to quit the application.
+ */
+void GUIControler::closeAllWindows()
+{
+    if (m_pClientWindow)
+        m_pClientWindow->close();
+    if (m_pSceneViewerWindow)
+        m_pSceneViewerWindow->close();
+    if (m_pPreferenceDialog)
+        m_pPreferenceDialog->close();
+    while (m_pProjectorWindows.size() > 0) {
+        QProjectorWindow* pProjectorWindow = m_pProjectorWindows.takeAt(0);
+        delete pProjectorWindow;
+    }
+}
+
+/**
+ * Restore settings of the DesignView and the SceneViewer.
+ *
+ * @param Parent XML element of the DesignView and the SceneViewer settings.
+ */
+bool GUIControler::initFromDOMElement(const QDomElement& element)
+{
+    if (m_pDesignViewWindow && !element.firstChildElement("DesignViewWindow").isNull())
+    {
+        m_pDesignViewWindow->initFromDOMElement(element.firstChildElement("DesignViewWindow"));
+    }
+    if (!element.firstChildElement("SceneViewerWindow").isNull())
+    {
+        m_sceneViewerSettings = element.firstChildElement("SceneViewerWindow");
+        if (!m_pSceneViewerWindow && m_sceneViewerSettings.attribute("show") == "true")
+            showSceneViewerWindow();
+        else if (m_pSceneViewerWindow)
+            m_pSceneViewerWindow->initFromDOMElement(m_sceneViewerSettings);
+    }
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current DesignView and SceneViewer as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current DesignView and SceneViewersettings as XML data.
+ */
+QDomElement GUIControler::domElement(const QString& name, QDomDocument& doc)
+{
+    QDomElement gui = doc.createElement(name);
+    if (m_pDesignViewWindow)
+        gui.appendChild(m_pDesignViewWindow->domElement("DesignViewWindow", doc));
+    if (m_pSceneViewerWindow)
+        gui.appendChild(m_pSceneViewerWindow->domElement("SceneViewerWindow", doc));
+    else
+        gui.appendChild(m_sceneViewerSettings);
+    return gui;
+}
Index: projectionDesigner/trunk/projdesigner/src/ProjectionModel.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/ProjectionModel.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/ProjectionModel.cpp	(revision 4)
@@ -0,0 +1,732 @@
+#include <QImage>
+#include <QPainter>
+#include <QGLPixelBuffer>
+
+#include "Scene.h"
+#include "Screen.h"
+#include "Channel.h"
+#include "RSync.h"
+#include "Exporter.h"
+#include "GUIControler.h"
+
+#include "ProjectionModel.h"
+
+using namespace projection;
+
+QDir ProjectionModel::pluginsDir;
+QStringList ProjectionModel::pluginFileNames;
+QList<ProjectorInterface*> ProjectionModel::projector_interfaces;
+QList<SceneInterface*> ProjectionModel::scene_interfaces;
+
+Q_IMPORT_PLUGIN(projdesigner_default)
+
+/**
+ * Constructor.
+ */
+ProjectionModel::ProjectionModel() : QObject()
+{
+		loadPlugins();
+
+    m_pScene = new Scene(this);
+    m_pScreen = new Screen(this);
+
+    m_pSelectedChannel = NULL;
+
+    m_projectorAreaTexIndex = 0;
+    m_viewAreaTexIndex = 0;
+
+    m_designMode = DESIGN_MODE_DISTORTIONMAP;
+
+    m_bBlockUpdate = false;
+
+    m_pRSync = new RSync(this);
+    m_pExporter = new Exporter(this);
+    m_pGUI = new GUIControler(this);
+
+    m_pGLWidget = NULL;
+    m_pPBuffer = NULL;
+
+#ifdef _DEBUG
+    m_updateViewsCount = 0;
+    m_updateOffscreenCount = 0;
+#endif // _DEBUG
+}
+
+/**
+ * Destructor.
+ */
+ProjectionModel::~ProjectionModel()
+{
+    if (glIsTexture(m_projectorAreaTexIndex))
+        glDeleteTextures(1, &m_projectorAreaTexIndex);
+    if (m_pRSync->isServer())
+    {
+        while (getNumChannels() > 0)
+            removeChannel(0);
+    }
+    delete m_pScreen;
+    delete m_pScene;
+
+    delete m_pRSync;
+    delete m_pExporter;
+    delete m_pGUI;
+}
+
+/**
+ * Initialize as a server.
+ *
+ * @param portNo Port number.
+ */
+void ProjectionModel::initServer(int portNo)
+{
+    m_pRSync->initServer(portNo);
+    m_pGUI->init(true);
+}
+
+/**
+ * Initialize as a client.
+ *
+ * @param address Client address.
+ * @param portNo Port number.
+ */
+void ProjectionModel::initClient(const QString& address, int portNo)
+{
+    m_pRSync->initClient(address, portNo);
+    m_pGUI->init(false);
+}
+
+/**
+ * Add a new channel.
+ *
+ * @return New channel.
+ */
+Channel* ProjectionModel::addChannel()
+{
+    Channel* pChannel = new Channel(this);
+    if (m_pSelectedChannel)
+        *pChannel = *m_pSelectedChannel;
+    m_pChannels.push_back(pChannel);
+
+    return pChannel;
+}
+
+/**
+ * Retrieve the number of the channels.
+ *
+ * @return The number of the channels.
+ */
+unsigned int ProjectionModel::getNumChannels() const
+{
+    return m_pChannels.size();
+}
+
+/**
+ * Retrieve a channel object
+ *
+ * @param index Index of channel to retrieve.
+ * @return Channel object.
+ */
+Channel* ProjectionModel::getChannel(int index) const
+{
+    if (index >= 0 && index < m_pChannels.size())
+        return m_pChannels[index];
+    return NULL;
+
+}
+
+/**
+ * Retrieve Index of the specified channel.
+ *
+ * @param pChannel Channel object.
+ * @return Index of the specified channel.
+ */
+int ProjectionModel::getChannelIndex(Channel* pChannel) const
+{
+    for (int i=0; i<m_pChannels.size(); ++i)
+        if (m_pChannels[i] == pChannel)
+            return i;
+    return -1;
+}
+
+/**
+ * Remove the specified channel.
+ *
+ * @param index Index of the channel to remove.
+ */
+void ProjectionModel::removeChannel(int index)
+{
+    if (index < 0)
+        return;
+
+    Channel* pChannel = m_pChannels.takeAt(index);
+    if (m_pSelectedChannel == pChannel) {
+        m_pGUI->selectChannel(NULL);
+        m_pSelectedChannel = NULL;
+    }
+    if (pChannel) {
+        m_pGUI->removeChannel(pChannel);
+        delete pChannel;
+    }
+
+    updateViews();
+}
+
+/**
+ * Remove all channels.
+ */
+void ProjectionModel::removeAllChannels()
+{
+    m_pSelectedChannel = NULL;
+    m_pGUI->selectChannel(NULL);
+
+    while (getNumChannels() > 0)
+        removeChannel(0);
+
+    m_pGUI->updateGUI();
+}
+
+/**
+ * Select a channel.
+ *
+ * @param pChannel Channel object to select.
+ */
+void ProjectionModel::selectChannel(Channel* pChannel)
+{
+    if (m_pSelectedChannel != pChannel)
+    {
+        m_pSelectedChannel = pChannel;
+        m_pGUI->selectChannel(pChannel);
+        updateViews();
+    }
+}
+
+/**
+ * Retrieve the selected channel object.
+ *
+ * @return Selected channel object.
+ */
+Channel* ProjectionModel::getSelectedChannel() const
+{
+    return m_pSelectedChannel;
+}
+
+/**
+ * Select the previous channel.
+ */
+void ProjectionModel::selectPreviousChannel()
+{
+    if (m_pChannels.size() == 0) return;
+
+    if (m_pSelectedChannel)
+        selectChannel(getChannel((getChannelIndex(m_pSelectedChannel)-1)%getNumChannels()));
+    else
+        selectChannel(getChannel(getNumChannels()-1));
+}
+
+/**
+ * Select the next channel.
+ */
+void ProjectionModel::selectNextChannel()
+{
+    if (m_pChannels.size() == 0) return;
+
+    if (m_pSelectedChannel)
+        selectChannel(getChannel((getChannelIndex(m_pSelectedChannel)+1)%getNumChannels()));
+    else
+        selectChannel(getChannel(0));
+}
+
+/**
+ * Check whether any channels with the specified name is existing or not.
+ *
+ * @return True if a channel with the specified name is existing.
+ */
+bool ProjectionModel::hasChannel(const QString& name) const
+{
+    for (int i=0; i<m_pChannels.size(); ++i)
+        if (m_pChannels.at(i)->getName() == name)
+            return true;
+    return false;
+}
+
+/**
+ * Create a unique name for specified channel.
+ *
+ * @param name Candidate name of channel. It may not be a unique name.
+ * @param pChannel Channel object to give a name.
+ * @return Unique name for the specified channel.
+ */
+QString ProjectionModel::getUniqueName(const QString& name, Channel* pChannel) const
+{
+    bool bUnique = true;
+    int i;
+    for (i=0; i<m_pChannels.size(); ++i)
+        if (m_pChannels[i] != pChannel && m_pChannels[i]->getName() == name)
+            bUnique = false;
+    if (!bUnique) {
+        int count = 0;
+        QString uniqueName;
+        while (true) {
+            uniqueName = name + QString("_%1").arg(count);
+            bUnique = true;
+            for (i=0; i<m_pChannels.size(); ++i)
+                if (m_pChannels[i]->getName() == uniqueName)
+                    bUnique = false;
+            if (bUnique) break;
+            count++;
+        }
+        return uniqueName;
+    }
+
+    return name;
+}
+
+/**
+ * Create a projection area texture and retrieve its texture object index.
+ *
+ * @return Texture object index of the projection area texture.
+ */
+GLuint ProjectionModel::getProjectorAreaTexture()
+{
+    if (m_projectorAreaTexIndex == 0)
+    {
+        QPixmap pixmap(256, 256);
+        pixmap.fill(QColor(0, 0, 64));
+        QPainter painter(&pixmap);
+        painter.setPen(QColor(255, 255, 255));
+        painter.drawRect(0, 0, 255, 255);
+        m_projectorAreaTexIndex = getGUI()->getGLWidget()->bindTexture(pixmap);
+    }
+    return m_projectorAreaTexIndex;
+}
+
+/**
+ * Create a view area texture and retrieve its texture object index.
+ *
+ * @return Texture object index of the view area texture.
+ */
+GLuint ProjectionModel::getViewAreaTexture()
+{
+    if (m_viewAreaTexIndex == 0)
+    {
+        QPixmap pixmap(256, 256);
+        pixmap.fill(QColor(64, 64, 0));
+        QPainter painter(&pixmap);
+        painter.setPen(QColor(255, 255, 255));
+        painter.drawRect(0, 0, 255, 255);
+        m_viewAreaTexIndex = getGUI()->getGLWidget()->bindTexture(pixmap);
+    }
+    return m_viewAreaTexIndex;
+}
+
+/**
+ * Set design mode.
+ *
+ * @param designMode Design mode.
+ */
+void ProjectionModel::setDesignMode(DESIGN_MODE designMode)
+{
+    if (m_designMode != designMode)
+    {
+        m_designMode = designMode;
+        updateViews();
+
+        QDomDocument doc;
+        doc.appendChild(domElement("Model", doc));
+        getRSync()->sendChanges(RSYNC_COMMAND_MODEL, doc.toString(0));
+    }
+}
+
+/**
+ * Retrieve the current design mode.
+ *
+ * @param designMode Design mode.
+ */
+DESIGN_MODE ProjectionModel::getDesignMode() const
+{
+    return m_designMode;
+}
+
+/**
+ * Block or unblock to update views.
+ *
+ * @param bBlock True to block updating views.
+ */
+void ProjectionModel::setBlockUpdate(bool bBlock)
+{
+    m_bBlockUpdate = bBlock;
+}
+
+/**
+    * Check whether blocking or not update views.
+    *
+    * @return True if blocking to update views.
+    */
+bool ProjectionModel::getBlockUpdate() const
+{
+    return m_bBlockUpdate;
+}
+
+/**
+ * Redraw all views (DesignViewWindow and ProjectorWindows).
+ */
+void ProjectionModel::updateViews()
+{
+#ifdef _DEBUG
+    m_updateViewsCount++;
+#endif // _DEBUG
+
+    if (!m_bBlockUpdate)
+        m_pGUI->updateViews();
+}
+
+/**
+ * Redraw off-screen buffer of the specified channel, then redraw all views.
+ */
+void ProjectionModel::updateViewAndOffscreens()
+{
+#ifdef _DEBUG
+    m_updateOffscreenCount++;
+#endif // _DEBUG
+
+    for (int i=0; i<m_pChannels.size(); ++i)
+        m_pChannels[i]->renderSceneToViewBuffer();
+
+    if (!m_bBlockUpdate)
+        m_pGUI->updateViews();
+}
+
+/**
+ * Load projection settings from a file.
+ *
+ * @param fileName File name to load.
+ * @return True if successfully loaded.
+ */
+bool ProjectionModel::loadFile(const QString& fileName)
+{
+    QFile file(fileName);
+    if (!file.open(QIODevice::ReadOnly))
+        return false;
+
+    QDomDocument doc;
+    doc.setContent(&file);
+    file.close();
+
+    if(!restoreSettings(doc))
+		return false;
+
+    return true;
+}
+
+/**
+ * Save the current projection settings to a file.
+ *
+ * @param fileName File name to save.
+ * @return True if successfully saved.
+ */
+bool ProjectionModel::saveFile(const QString& fileName)
+{
+    QFile file(fileName);
+    if (file.open(QIODevice::WriteOnly|QIODevice::Truncate))
+    {
+        QTextStream out(&file);
+        QDomDocument doc;
+
+        storeSettings(doc);
+
+        doc.save(out, 4);
+        file.flush();
+        file.close();
+
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Restart from a new file.
+ *
+ * @return True if everything is ok.
+ */
+bool ProjectionModel::newFile()
+{
+    QDomDocument doc;
+    doc.setContent(QString(""));
+    restoreSettings(doc);
+		return true;
+}
+
+/**
+ * Restore the model from XML data.
+ *
+ * @param element Parent XML element of the model data.
+ */
+bool ProjectionModel::initFromDOMElement(const QDomElement& element)
+{
+	if (!element.isNull())
+	{
+		if (element.attribute("designMode") == "distortionMap")
+            setDesignMode(DESIGN_MODE_DISTORTIONMAP);
+        else
+            setDesignMode(DESIGN_MODE_BLENDMAP);
+	}
+
+	return true;	// Todo: Secure this funtion and return only true if no critical error occurs
+}
+
+/**
+ * Store the current model as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen data as XML data.
+ */
+QDomElement ProjectionModel::domElement(const QString& name, QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement(name);
+    de.setAttribute("designMode", m_designMode==DESIGN_MODE_DISTORTIONMAP?"distortionMap":"blendMap");
+
+    return de;
+}
+
+/**
+ * Restore projection settings from xml data.
+ *
+ * @param doc XML document to restore the projection settings from.
+ */
+bool ProjectionModel::restoreSettings(QDomDocument& doc)
+{
+	// separate from environment (cocoon)
+    blockSignals(true);
+    m_pRSync->setBlockSync(true);
+
+	// Deleting old Channels
+    while (getNumChannels() > 0)
+        removeChannel(0);
+
+	// ??
+    QDomElement main;
+    main = doc.documentElement();
+
+	// Setting data version
+	QString version = main.attribute("version");
+	if (version.isNull()) version="1.0.0";
+
+	// Initialising channels
+	QDomElement channel = main.firstChildElement("Channel");
+    while (!channel.isNull()) {
+        Channel* pChannel = addChannel();
+        if( !pChannel->initFromDOMElement(channel, version) )
+			return false;
+        channel = channel.nextSiblingElement("Channel");
+    }
+
+	// Now initializing other parts (its important that the channels are initialized first, because then sync to remote channels is possible.)
+    if( !initFromDOMElement(main.firstChildElement("Model")) )
+		return false;
+    if( !m_pScene->initFromDOMElement(main.firstChildElement("Scene")) )
+		return false;
+    if( !m_pScreen->initFromDOMElement(main.firstChildElement("Screen")) )
+		return false;
+	if( !m_pExporter->initFromDOMElement(main.firstChildElement("Exporter")) )
+		return false;
+
+
+    if (m_pRSync->isServer())
+    {
+        if (!main.firstChildElement("GUI").isNull())
+			if( !m_pGUI->initFromDOMElement(main.firstChildElement("GUI")) )
+				return false;
+		m_pGUI->updateGUI();
+    }
+    
+	// Reopen to environment :)
+    m_pRSync->setBlockSync(false);
+
+    m_pRSync->sendReloadSettings();	// <== Function secured: is only performed when server
+
+	// Reopen to environment :)
+    blockSignals(false);
+
+    selectNextChannel();
+
+    updateViewAndOffscreens();
+
+	return true;
+}
+
+/**
+ * Store projection settings to xml data.
+ *
+ * @param doc XML document to store the projection settings.
+ */
+void ProjectionModel::storeSettings(QDomDocument& doc)
+{
+    QDomElement main = doc.createElement("Distortion");
+
+	main.setAttribute("version", APPLICATION_VERSION);
+
+    main.appendChild(domElement("Model", doc));
+    main.appendChild(m_pExporter->domElement("Exporter", doc));
+    main.appendChild(m_pScene->domElement("Scene", doc));
+    main.appendChild(m_pScreen->domElement("Screen", doc));
+    main.appendChild(m_pExporter->domElement("Exporter", doc));
+    for (int i=0; i<m_pChannels.size(); ++i)
+        main.appendChild(m_pChannels[i]->domElement("Channel", doc));
+
+    main.appendChild(m_pGUI->domElement("GUI", doc));
+
+    doc.appendChild(main);
+}
+
+/**
+ * Retrieve the scene object.
+ *
+ * @return Scene object.
+ */
+Scene* ProjectionModel::getScene() const
+{
+    return m_pScene;
+}
+
+/**
+ * Retrieve the screen object.
+ *
+ * @return Screen object.
+ */
+Screen* ProjectionModel::getScreen() const
+{
+    return m_pScreen;
+}
+
+/**
+ * Retrieve the remote state synchronize object.
+ *
+ * @return Remote state synchronize object.
+ */
+RSync* ProjectionModel::getRSync() const
+{
+    return m_pRSync;
+}
+
+/**
+ * Retrieve the exporter object.
+ *
+ * @return Exporter object.
+ */
+Exporter* ProjectionModel::getExporter() const
+{
+    return m_pExporter;
+}
+
+/**
+ * Retrieve the GUI controler object.
+ *
+ * @return GUI controler object.
+ */
+GUIControler* ProjectionModel::getGUI() const
+{
+    return m_pGUI;
+}
+
+/**
+ * Loads the plugins
+ */
+void ProjectionModel::loadPlugins()
+{
+    foreach (QObject *plugin, QPluginLoader::staticInstances())
+	{
+	    ProjectorInterface *projector_interface = qobject_cast<ProjectorInterface*>(plugin);
+	    if (projector_interface)
+	    {
+		projector_interfaces += projector_interface;
+	    }
+	    SceneInterface *scene_interface = qobject_cast<SceneInterface*>(plugin);
+	    if (scene_interface)
+	    {
+		scene_interfaces += scene_interface;
+	    }
+	}
+
+    pluginsDir = QDir(qApp->applicationDirPath());
+
+    // The following ifdef/endif block is from Qt Examples
+#if defined(Q_OS_WIN)
+//    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
+//        pluginsDir.cdUp();
+#elif defined(Q_OS_MAC)
+    if (pluginsDir.dirName() == "MacOS") {
+        pluginsDir.cdUp();
+        pluginsDir.cdUp();
+        pluginsDir.cdUp();
+    }
+#endif
+    if (!pluginsDir.cd("../lib")) return;
+
+    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
+        QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
+        QObject *plugin = loader.instance();
+        if (plugin) {
+            pluginFileNames += fileName;
+
+	    ProjectorInterface *projector_interface = qobject_cast<ProjectorInterface*>(plugin);
+	    if (projector_interface)
+	    {
+		projector_interfaces += projector_interface;
+	    }
+	    SceneInterface *scene_interface = qobject_cast<SceneInterface*>(plugin);
+	    if (scene_interface)
+	    {
+		scene_interfaces += scene_interface;
+	    }
+        }
+	else
+	{
+	    QString errorString = loader.errorString();
+	    QString message;
+	    if (errorString=="Unknown error")
+	    {
+		message = trUtf8("<p><b>%1</b>: Le plugin a Ã©tÃ© rejetÃ©<br><i><u>Raison invoquÃ©e par le loader</u>: %2</i><br>ATTENTION: Cela peut venir d'une configuration en debug du plugin dynamique.<p><b>OK</b> lance quand mÃªme l'application,<br><b>Cancel</b> annule le lancement.").arg(fileName).arg(errorString);
+	    }
+	    else
+	    {
+		message = trUtf8("<p><b>%1</b>: Le plugin a Ã©tÃ© rejetÃ©<br><i><u>Raison invoquÃ©e par le loader</u>: %2</i><p><b>OK</b> lance quand mÃªme l'application,<br><b>Cancel</b> annule le lancement.").arg(fileName).arg(errorString);
+	    }
+	    if (QMessageBox::Cancel==QMessageBox::warning(NULL, trUtf8("Attention"), message, QMessageBox::Ok|QMessageBox::Cancel))
+		exit(-1);
+	}
+    }
+}
+
+/**
+ * Set a GLWidget for the current render context.
+ *
+ * @parma pGLWidget GLWidget of the current render context.
+ */
+void ProjectionModel::setRenderContext(QGLWidget* pGLWidget)
+{
+    m_pGLWidget = pGLWidget;
+    m_pPBuffer = NULL;
+}
+
+/**
+ * Set a P-Buffer for the current render context.
+ *
+ * @parma pPBuffer P-Buffer of the current render context.
+ */
+void ProjectionModel::setRenderContext(QGLPixelBuffer* pPBuffer)
+{
+    m_pGLWidget = NULL;
+    m_pPBuffer = pPBuffer;
+}
+
+/**
+ * Activate the current render context.
+ */
+void ProjectionModel::activateRenderContext()
+{
+    if (m_pGLWidget)
+        m_pGLWidget->makeCurrent();
+    if (m_pPBuffer)
+        m_pPBuffer->makeCurrent();
+}
Index: projectionDesigner/trunk/projdesigner/src/RSync.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/RSync.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/RSync.cpp	(revision 4)
@@ -0,0 +1,362 @@
+#include <QtNetwork/QtNetwork>
+#include <QApplication>
+#include <QMessageBox>
+
+#include "ProjectionModel.h"
+#include "Screen.h"
+#include "Scene.h"
+#include "Channel.h"
+#include "Exporter.h"
+#include "GUIControler.h"
+
+#include "RSync.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pModel Projection model.
+ */
+RSync::RSync(ProjectionModel* pModel) : QObject()
+{
+    m_pModel = pModel;
+
+    m_hostName = QHostInfo::localHostName();
+    m_pTcpServer = NULL;
+    m_pTcpClient = NULL;
+    m_portNo = DEFAULT_PORT_NO;
+    m_serverAddress = QHostInfo::localHostName();
+
+    m_bBlockSync = false;
+}
+
+/**
+ * Destructor.
+ */
+RSync::~RSync()
+{
+    if (!m_bServer)
+        sendChanges(RSYNC_COMMAND_DISCONNECT, "Disconnect");
+
+    if (m_pTcpServer)
+        delete m_pTcpServer;
+    if (m_pTcpClient)
+        delete m_pTcpClient;
+}
+
+/**
+ * Initialize as a server.
+ *
+ * @param portNo Port number.
+ */
+void RSync::initServer(int portNo)
+{
+    m_bServer = true;
+
+    if (portNo != 0)
+        m_portNo = portNo;
+
+    m_bServer = true;
+
+//return;
+
+    m_pTcpServer = new QTcpServer(m_pModel);
+    if (!m_pTcpServer->listen(QHostAddress::Any, m_portNo)) {
+        QMessageBox::critical(NULL, APPLICATION_NAME,
+                              QString("Unable to start the server: %1.").arg(m_pTcpServer->errorString()));
+        return;
+    }
+    connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(acceptNewClient()));
+}
+
+/**
+ * Initialize as a client.
+ *
+ * @param address Client address.
+ * @param portNo Port number.
+ */
+void RSync::initClient(const QString& address, int portNo)
+{
+    m_bServer = false;
+
+    if (!address.isEmpty()) m_serverAddress = address;
+    if (portNo != 0) m_portNo = portNo;
+
+    m_pTcpClient = new QTcpSocket(this);
+    m_pTcpClient->setReadBufferSize(0);
+    connect(m_pTcpClient, SIGNAL(readyRead()), this, SLOT(recvSettings()));
+    connect(m_pTcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
+
+    connectToServer();
+}
+
+/**
+ * Send a sync command to clients.
+ *
+ * @param command Synchronize command.
+ * @param command Synchronize data.
+ */
+void RSync::sendChanges(RSYNC_COMMAND command, const QString& data)
+{
+    if (m_bBlockSync)
+        return;
+
+    QByteArray block;
+    QDataStream out(&block, QIODevice::WriteOnly);
+    out.setVersion(QDataStream::Qt_4_5);
+    out << (quint32)0;
+    out << (int)command;
+    out << data;
+    out.device()->seek(0);
+    out << (quint32)(block.size() - sizeof(quint32));
+
+    for (int i=0; i<m_pClientConnections.size(); ++i)
+    {
+        if (m_pClientConnections[i]->isValid()) {
+            m_pClientConnections[i]->write(block);
+            m_pClientConnections[i]->flush();
+        }
+    }
+}
+
+/**
+ * Send a reload command to clients.
+ */
+void RSync::sendReloadSettings()
+{
+    if (m_bBlockSync)
+        return;
+
+    if (m_bServer)
+    {
+        QDomDocument doc;
+        m_pModel->storeSettings(doc);
+        sendChanges(RSYNC_COMMAND_RELOAD, doc.toString(0));
+    }
+}
+
+/**
+ * Connect to a server.
+ */
+void RSync::connectToServer()
+{
+    m_pTcpClient->abort();
+    m_pTcpClient->connectToHost(m_serverAddress, m_portNo);
+}
+
+/**
+ * Called when a new client connects to the server. Send all states to synchronize.
+ */
+void RSync::acceptNewClient()
+{
+    QDomDocument doc;
+    m_pModel->storeSettings(doc);
+
+    QByteArray block;
+    QDataStream out(&block, QIODevice::WriteOnly);
+    out.setVersion(QDataStream::Qt_4_5);
+    out << (quint32)0;
+    out << (int)RSYNC_COMMAND_INIT;
+    out << doc.toString(0);
+    out.device()->seek(0);
+    out << (quint32)(block.size() - sizeof(quint32));
+
+    QTcpSocket* pClientConnection = m_pTcpServer->nextPendingConnection();
+//  connect(pClientConnection, SIGNAL(disconnected()),
+//            pClientConnection, SLOT(deleteLater()));
+    m_pClientConnections.push_back(pClientConnection);
+
+    m_pModel->getGUI()->showStatusBarMessage(QString("%1 connected").arg(pClientConnection->peerAddress().toString()), 2000);
+
+    pClientConnection->write(block);
+    pClientConnection->flush();
+//  pClientConnection->disconnectFromHost();
+
+	// Inform Clients about acutal loaded Scene/Model/Screen
+	m_pModel->getScreen()->notifyRedraw();
+}
+
+/**
+ * Called when a new synchronize message is received.
+ */
+void RSync::recvSettings()
+{
+    QDataStream in(m_pTcpClient);
+    in.setVersion(QDataStream::Qt_4_5);
+
+
+    while (m_pTcpClient->bytesAvailable() > 0)
+    {
+        static quint32 blockSize = 0;
+        if (blockSize == 0) {
+            if (m_pTcpClient->bytesAvailable() < (int)sizeof(quint32))
+                return;
+            in >> blockSize;
+        }
+
+        if (m_pTcpClient->bytesAvailable() < blockSize)
+            return;
+
+        int command;
+        in >> command;
+
+        QString data;
+        in >> data;
+
+        blockSize = 0;
+
+        switch (command)
+        {
+            case RSYNC_COMMAND_INIT:
+            {
+                m_lastErrorString = "";
+                m_pModel->getGUI()->appendClientLog(tr("Connected to server : %1:%2.").arg(m_serverAddress).arg(m_portNo));
+
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->restoreSettings(doc);
+                break;
+            }
+            case RSYNC_COMMAND_VIEWPOINT:
+            {
+                m_pModel->getScene()->setCameraViewpoint(data);
+                break;
+            }
+            case RSYNC_COMMAND_EXPORT:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->getExporter()->initFromDOMElement(doc.firstChildElement("Exporter"));
+                break;
+            }
+            case RSYNC_COMMAND_MODEL:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->initFromDOMElement(doc.firstChildElement("Model"));
+                break;
+            }
+            case RSYNC_COMMAND_SCENE:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->getScene()->initFromDOMElement(doc.firstChildElement("Scene"));
+                break;
+            }
+            case RSYNC_COMMAND_SCREEN:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->getScreen()->initFromDOMElement(doc.firstChildElement("Screen"));
+                break;
+            }
+            case RSYNC_COMMAND_CHANNEL:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                QDomElement channel = doc.firstChildElement("Channel");
+                QString channelName = channel.attribute("name");
+                for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i) {
+                    if (channelName == m_pModel->getChannel(i)->getName())
+                        m_pModel->getChannel(i)->initFromDOMElement(channel, APPLICATION_VERSION);
+                }
+                break;
+            }
+            case RSYNC_COMMAND_GUI:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->getGUI()->initFromDOMElement(doc.firstChildElement("GUI"));
+                break;
+            }
+            case RSYNC_COMMAND_RELOAD:
+            {
+                QDomDocument doc;
+                doc.setContent(data);
+                m_pModel->restoreSettings(doc);
+                break;
+            }
+            case RSYNC_COMMAND_EXPORTFILE:
+            {
+                m_pModel->getExporter()->exportDataset(data);
+                break;
+            }
+            case RSYNC_COMMAND_DISCONNECT:
+            {
+                m_pModel->removeAllChannels();
+                m_lastErrorString = "";
+                m_pModel->getGUI()->appendClientLog(tr("Connection shutdowned."));
+
+                connectToServer();
+                break;
+            }
+            case RSYNC_COMMAND_END:
+            {
+                qApp->closeAllWindows();
+            }
+        }
+    }
+}
+
+/**
+ * Called when a network error is occured.
+ */
+void RSync::displayNetworkError(QAbstractSocket::SocketError socketError)
+{
+/*
+    switch (socketError) {
+    case QAbstractSocket::RemoteHostClosedError:
+        break;
+    case QAbstractSocket::HostNotFoundError:
+        QMessageBox::information(NULL, APPLICATION_NAME,
+                                 tr("The host was not found. Please check the "
+                                    "host name and port settings."));
+        break;
+    case QAbstractSocket::ConnectionRefusedError:
+        QMessageBox::information(NULL, APPLICATION_NAME,
+                                 tr("The connection was refused by the peer. "
+                                    "Make sure the Multichannnel Projection Designer server is running, "
+                                    "and check that the host name and port settings are correct."));
+        break;
+    default:
+        QMessageBox::information(NULL, APPLICATION_NAME,
+                                 tr("The following error occurred: %1.")
+                                 .arg(m_pTcpClient->errorString()));
+    }
+*/
+
+    if (socketError != QAbstractSocket::UnknownSocketError &&
+        m_lastErrorString != m_pTcpClient->errorString())
+    {
+        m_pModel->removeAllChannels();
+        m_lastErrorString = m_pTcpClient->errorString();
+        m_pModel->getGUI()->appendClientLog(m_lastErrorString);
+        m_pModel->getGUI()->appendClientLog(tr("Try connecting again..."));
+    }
+
+    QTimer* pTimer = new QTimer(this);
+    connect(pTimer, SIGNAL(timeout()), this, SLOT(connectToServer()));
+    pTimer->setSingleShot(true);
+    pTimer->start(1000);
+}
+
+/**
+ * Set sync message blocking.
+ *
+ * @param bBlock True to block sending sync data to clients.
+ */
+void RSync::setBlockSync(bool bBlock)
+{
+    m_bBlockSync = bBlock;
+}
+
+/**
+ * Check whether sync message is blocked or not.
+ *
+ * @param bBlock True to block sending sync data to clients.
+ */
+bool RSync::getBlockSync() const
+{
+    return m_bBlockSync;
+}
Index: projectionDesigner/trunk/projdesigner/src/Scene.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Scene.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Scene.cpp	(revision 4)
@@ -0,0 +1,431 @@
+#include "ProjectionModel.h"
+#include "Scene.h"
+#include "RSync.h"
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+
+#include "GUIControler.h"
+
+using namespace projection;
+using namespace gmtl;
+
+static void dom2vp(const QDomElement& parent, gmtl::Vec3f& center, gmtl::Quatf& rot, float& distance)
+{
+    if (parent.isNull())
+        return;
+
+    center[0] = parent.attribute("centerx", "0").toFloat();
+    center[1] = parent.attribute("centery", "0").toFloat();
+    center[2] = parent.attribute("centerz", "0").toFloat();
+    rot[0] = parent.attribute("rotx", "0").toFloat();
+    rot[1] = parent.attribute("roty", "0").toFloat();
+    rot[2] = parent.attribute("rotz", "0").toFloat();
+    rot[3] = parent.attribute("rotw", "1").toFloat();
+    distance = parent.attribute("distance", "1").toFloat();
+}
+
+static QDomElement vp2dom(QDomDocument& doc, const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
+{
+    QDomElement cm = doc.createElement("Camera");
+    cm.setAttribute("centerx", QString::number(center[0]));
+    cm.setAttribute("centery", QString::number(center[1]));
+    cm.setAttribute("centerz", QString::number(center[2]));
+    cm.setAttribute("rotx", QString::number(rot[0]));
+    cm.setAttribute("roty", QString::number(rot[1]));
+    cm.setAttribute("rotz", QString::number(rot[2]));
+    cm.setAttribute("rotw", QString::number(rot[3]));
+    cm.setAttribute("distance", QString::number(distance));
+    return cm;
+}
+
+static gmtl::Matrix44f vp2matrix(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
+{
+    return makeTrans<Matrix44f>(center) * makeRot<Matrix44f>(rot) * makeTrans<Matrix44f>(Vec3f(0.0f, 0.0f, distance));
+}
+
+/**
+ * Constructor.
+ *
+ * @param pModel Projection model.
+ */
+Scene::Scene(ProjectionModel* pModel) : QObject()
+{
+    m_pModel = pModel;
+	foreach (SceneInterface *scene_interface, ProjectionModel::scene_interfaces)
+	{
+    	Q_ASSERT(NULL!=scene_interface);
+	    foreach (QString scene_name, scene_interface->scenes())
+		{
+		    SceneContent* scene_content = scene_interface->newSceneContent(scene_name);
+			m_pContents.push_back(scene_content);
+		}
+	}
+	reset();
+
+    m_bShowGrid = true;
+	m_gridSize = 5;
+
+    m_cameraDistance = 2.0f;
+    m_cameraRot = makeRot<Quatf>(AxisAnglef(Math::deg2Rad(45.0f), Vec3f(0.0f, 1.0f, 0.0f))) *
+                  makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-45.0f), Vec3f(1.0f, 0.0f, 0.0f)));
+}
+
+/**
+ * Destructor.
+ */
+Scene::~Scene()
+{
+    while (m_pContents.count() > 0) {
+        SceneContent* pContent = m_pContents.takeAt(0);
+        if (pContent) delete pContent;
+    }
+}
+
+/**
+ * Retrieve Projection model.
+ *
+ * @return Projection model.
+ */
+ProjectionModel* Scene::getModel() const
+{
+    return  m_pModel;
+}
+
+/**
+ * Retrieve name of the scene content.
+ *
+ * @param index Index of the scene content.
+ * @return Name of the scene content.
+ */
+QString Scene::getContentName(int index) const
+{
+    Q_ASSERT(index < m_pContents.size());
+	SceneContent *sc = m_pContents[index];
+	Q_ASSERT(sc);
+	QString name = sc->getFullName();
+	return name;
+}
+
+/**
+ * Retrieve the number of the scene content.
+ *
+ * @return Number of the scene content.
+ */
+unsigned int Scene::getNumContents() const
+{
+    return m_pContents.size();
+}
+
+/**
+ * Retrieve scene content object.
+ *
+ * @param shapeName Name of the scene content object.
+ * @return Scene content object.
+ */
+SceneContent* Scene::getContent(const QString& contentName) const
+{
+    for (int i=0; i<m_pContents.size(); ++i)
+        if (getContentName(i) == contentName)
+		{
+            return m_pContents[i];
+		}
+    return NULL;
+}
+
+/**
+ * Select scene content by name.
+ *
+ * @param contentName Name of the scene content to select.
+ */
+void Scene::setCurrentContent(const QString& contentName)
+{
+    if (m_pCurrentContent && m_pCurrentContent->scene_name() == contentName)
+        return;
+    for (int i=0; i<m_pContents.size(); ++i) {
+        if (m_pContents[i]->getFullName() == contentName) {
+		    m_pCurrentContent = m_pContents[i];
+ 		    notifyRedraw();
+		}
+    }
+}
+
+/**
+ * Retrieve the name of the current scene content.
+ *
+ * @return Name of the current scene content.
+ */
+QString Scene::getCurrentContentName() const
+{
+	Q_ASSERT(NULL!=m_pCurrentContent);
+    return m_pCurrentContent->getFullName();
+}
+
+/**
+ * Retrieve current scene content object.
+ *
+ * @return Current scene content object.
+ */
+SceneContent* Scene::getCurrentContent() const
+{
+    return m_pCurrentContent;
+}
+
+/**
+ * Set viewpoint of the scene viewer.
+ *
+ * @param data Viewpoint as XML data.
+ */
+void Scene::setCameraViewpoint(const QString& data)
+{
+    Vec3f center;
+    Quatf rot;
+    float distance;
+    QDomDocument doc;
+    doc.setContent(data);
+    QDomElement camera = doc.firstChildElement("Camera");
+    dom2vp(camera, center, rot, distance);
+    setCameraViewpoint(center, rot, distance);
+}
+
+/**
+ * Set viewpoint data.
+ *
+ * @param center Viewpoint center.
+ * @param rot Viewpoint rotation.
+ * @param distance Viewpoint distance from trackball center.
+ */
+void Scene::setCameraViewpoint(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
+{
+    m_cameraCenter = center;
+    m_cameraRot = rot;
+    m_cameraDistance = distance;
+
+    if (m_pModel->getRSync()->isServer())
+    {
+        QDomDocument doc;
+        doc.appendChild(vp2dom(doc, m_cameraCenter, m_cameraRot, m_cameraDistance));
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_VIEWPOINT, doc.toString(0));
+    }
+
+    m_pModel->updateViewAndOffscreens();
+}
+
+/**
+ * Retrieve viewpoint matrix of the scene viewer.
+ *
+ * @return Viewpoint matrix.
+ */
+gmtl::Matrix44f Scene::getCameraMatrix() const
+{
+    return vp2matrix(m_cameraCenter, m_cameraRot, m_cameraDistance);
+}
+
+/**
+ * Put the camera at the center of the scene.
+ */
+void Scene::centerView()
+{
+    m_pModel->getGUI()->sceneCenterView();
+}
+
+/**
+ * Set camera to view all the scene.
+ */
+void Scene::viewAll()
+{
+    m_pModel->getGUI()->sceneViewAll();
+}
+
+/**
+ * Set transform matrix of the scene.
+ *
+ * @param matrix Transform matrix of the scene.
+ */
+void Scene::setMatrix(const TransformMatrix& matrix)
+{
+    m_transformMatrix = matrix;
+    m_pModel->updateViewAndOffscreens();
+}
+
+/**
+ * Draw the scene content.
+ */
+void Scene::draw()
+{
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    glPushMatrix();
+    glMultMatrixf(m_transformMatrix.getMatrix().getData());
+    m_pCurrentContent->draw(getModel()->getGUI()->getGLWidget(), getCameraMatrix().getData());
+    glPopMatrix();
+
+    glPopAttrib();
+}
+
+/**
+ * Show or hide the scene content in design view.
+ *
+ * @param bShowInDesignView True to show the scene content in design view.
+ */
+void Scene::setShowInDesignView(bool bShowInDesignView)
+{
+    m_bShowInDesignView = bShowInDesignView;
+    notifyRedraw();
+}
+
+/**
+ * Set size of the scene for SceneViewer.
+ *
+ * @param size Size of the scene.
+ */
+void Scene::setSize(float size)
+{
+    m_size = size;
+    m_pModel->getGUI()->setSceneSize(m_size);
+}
+
+/**
+ * Retrieve size of the scene.
+ *
+ * @return Size of the scene.
+ */
+float Scene::getSize() const
+{
+/*
+    Vec3f min, max;
+    m_pCurrentContent->getBoundingBox(min, max);
+    min = m_transformMatrix.getMatrix() * min;
+    max = m_transformMatrix.getMatrix() * max;
+    float minLength = length(min);
+    float maxLength = length(max);
+    return minLength>maxLength?minLength:maxLength;
+*/
+    return m_size;
+}
+
+/**
+ * Show or hide a grid frame with the scene content.
+ *
+ * @param bShowGrid True to show a grid frame, false to hide.
+ */
+void Scene::setShowGrid(bool bShowGrid)
+{
+    m_bShowGrid = bShowGrid;
+    notifyRedraw();
+}
+
+/**
+ * Set size of the grid frame.
+ *
+ * @param gridSize Size of the grid frame.
+ */
+void Scene::setGridSize(float gridSize)
+{
+    m_gridSize = gridSize;
+    notifyRedraw();
+}
+
+/**
+ * Notify to redraw the screen.
+ */
+void Scene::notifyRedraw()
+{
+    if (m_pModel->getRSync()->isServer())
+    {
+        QDomDocument doc;
+        doc.appendChild(domElement("Scene", doc));
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCENE, doc.toString(0));
+    }
+
+    m_pModel->getGUI()->updateSceneViewer();
+    m_pModel->updateViewAndOffscreens();
+}
+
+/**
+ * Restore the scene content from XML data.
+ *
+ * @param element Parent XML element of the scene content data.
+ */
+bool Scene::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        if (!element.firstChildElement("TransformMatrix").isNull())
+            m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix"));
+        setCurrentContent(element.attribute("contentName"));
+        m_bShowInDesignView = element.attribute("showInDesignView").toLower()=="true";
+        m_size = element.attribute("size").toFloat();
+        dom2vp(element.firstChildElement("Camera"), m_cameraCenter, m_cameraRot, m_cameraDistance);
+
+        QDomElement contents = element.firstChildElement("Contents");
+        QDomElement content = contents.firstChild().toElement();
+        while (!content.isNull()) {
+            SceneContent* pContent = getContent(content.attribute("name"));
+            if (pContent)
+                pContent->initFromDOMElement(content);
+            content = content.nextSiblingElement();
+        }
+    }
+	else
+	{
+			reset();
+	}
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current scene content as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current scene content data as XML data.
+ */
+QDomElement Scene::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc));
+    de.setAttribute("contentName", getCurrentContentName());
+    de.setAttribute("showInDesignView", (m_bShowInDesignView?"true":"false"));
+    de.setAttribute("size", m_size);
+    de.appendChild(vp2dom(doc, m_cameraCenter, m_cameraRot, m_cameraDistance));
+
+    QDomElement contents = doc.createElement("Contents");
+    for (int i=0; i<m_pContents.size(); ++i)
+        contents.appendChild(m_pContents[i]->domElement("Content", doc));
+    de.appendChild(contents);
+
+    return de;
+}
+
+/**
+ * Update the scene content.
+ *
+ * @param content Scene content from the widget.
+ */
+void Scene::updateSceneContent(const SceneContent& content)
+{
+	Q_ASSERT(m_pCurrentContent->getFullName()==content.getFullName());
+	if (!content.is_equal_to(*m_pCurrentContent))
+	{
+		m_pCurrentContent->copy_from(content);
+		notifyRedraw();
+	}
+}
+
+/**
+ * Reset the scene
+ */
+void Scene::reset()
+{
+	m_transformMatrix.reset();
+	Q_ASSERT(m_pContents.size()>1);
+	m_pCurrentContent = m_pContents[1]; // Teapot (but how to be sure?!)
+    m_bShowInDesignView = true;
+    m_size = 1000.0f;
+    m_cameraDistance = 2.0f;
+    m_cameraRot = makeRot<Quatf>(AxisAnglef(Math::deg2Rad(45.0f), Vec3f(0.0f, 1.0f, 0.0f))) *
+                  makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-45.0f), Vec3f(1.0f, 0.0f, 0.0f)));
+	for (int i=0; i<m_pContents.size(); ++i)
+        m_pContents[i]->reset();
+}
Index: projectionDesigner/trunk/projdesigner/src/Screen.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Screen.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Screen.cpp	(revision 4)
@@ -0,0 +1,527 @@
+#include "ProjectionModel.h"
+#include "Screen.h"
+#include "screen/ScreenDome.h"
+#include "screen/ScreenPlane.h"
+#include "screen/ScreenBox.h"
+#include "screen/ScreenModel.h"
+#include "Channel.h"
+#include "GUIControler.h"
+#include "RSync.h"
+#include "Exporter.h"
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor. Screen data / rendering class.
+ *
+ * @param Projection model.
+ */
+Screen::Screen(ProjectionModel* pSetup) : QObject()
+{
+    m_pModel = pSetup;
+
+    m_pShapes.push_back(new ScreenDome(this));
+    m_pShapes.push_back(new ScreenPlane(this));
+    m_pShapes.push_back(new ScreenBox(this));
+    m_pShapes.push_back(new ScreenModel(this));
+    m_pCurrentShape = m_pShapes[0]; // Dome
+
+	reset ();
+}
+
+/**
+ * Destructor.
+ */
+Screen::~Screen()
+{
+    while (m_pShapes.count() > 0) {
+        ScreenShape* pShape = m_pShapes.takeAt(0);
+        if (pShape) delete pShape;
+    }
+}
+
+/**
+ * Set transform matrix of the screen.
+ *
+ * @param matrix Transform matrix of the screen.
+ */
+void Screen::setMatrix(const TransformMatrix& matrix)
+{
+    m_transformMatrix = matrix;
+    notifyRedraw();
+}
+
+/**
+ * Retrieve name of the screen shape.
+ *
+ * @param index Index of the screen shape.
+ * @return Name of the screen shape.
+ */
+QString Screen::getShapeName(int index) const
+{
+    if (index < m_pShapes.size())
+        return m_pShapes[index]->getName();
+    return "None";
+}
+
+/**
+ * Retrieve the number of the screen shapes.
+ *
+ * @return Number of the screen shapes.
+ */
+unsigned int Screen::getNumShapes() const
+{
+    return m_pShapes.size();
+}
+
+/**
+ * Retrieve screen shape object.
+ *
+ * @param shapeName Name of the screen shape.
+ * @return Screen shape object.
+ */
+ScreenShape* Screen::getShape(const QString& shapeName) const
+{
+    for (int i=0; i<m_pShapes.size(); ++i)
+        if (m_pShapes[i]->getName() == shapeName)
+            return m_pShapes[i];
+    return NULL;
+}
+
+/**
+ * Select screen shape by name.
+ *
+ * @param shapeName Name of the screen shape to select.
+ */
+void Screen::setCurrentShape(const QString& shapeName)
+{
+    if (m_pCurrentShape && m_pCurrentShape->getName() == shapeName)
+        return;
+
+    for (int i=0; i<m_pShapes.size(); ++i) {
+        if (m_pShapes[i]->getName() == shapeName) {
+            m_pCurrentShape = m_pShapes[i];
+            notifyRedraw();
+        }
+    }
+}
+
+/**
+ * Retrieve the name of the current srceen shape.
+ *
+ * @return Name of the current screen shape.
+ */
+QString Screen::getCurrentShapeName() const
+{
+    return m_pCurrentShape->getName();
+}
+
+/**
+ * Retrieve the current screen shape object.
+ *
+ * @return Current screen shape object.
+ */
+ScreenShape* Screen::getCurrentShape() const
+{
+    return m_pCurrentShape;
+}
+
+/**
+ * Retrive the radius of the current screen.
+ *
+ * @return Radius of the current screen.
+ */
+float Screen::getSize() const
+{
+    Vec3f min, max;
+    m_pCurrentShape->getBoundingBox(min, max);
+    min = m_transformMatrix.getMatrix() * min;
+    max = m_transformMatrix.getMatrix() * max;
+    float minLength = length(min);
+    float maxLength = length(max);
+    return minLength>maxLength?minLength:maxLength;
+}
+
+/**
+ * Show or hide the wire frame mesh of the screen.
+ *
+ * @param bShowFrame True to show the wire frame mesh.
+ */
+void Screen::setShowFrame(bool bShowFrame)
+{
+    m_bShowFrame = bShowFrame;
+    notifyRedraw();
+}
+
+/**
+ * Set line width of the wire frame mesh of the screen.
+ *
+ * @param frameLineWidth Line width of the wire frame mesh of the screen.
+ */
+void Screen::setFrameLineWidth(float frameLineWidth)
+{
+    m_frameLineWidth = frameLineWidth;
+    notifyRedraw();
+}
+
+/**
+ * Set size of the off-screen buffer.
+ *
+ * @param width Width of the off-screen buffer.
+ * @param height Height of the off-screen buffer.
+ */
+void Screen::setBufferSize(int width, int height)
+{
+    if (m_bufferWidth != width || m_bufferHeight != height)
+    {
+        m_bufferWidth = width;
+        m_bufferHeight = height;
+        for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+            m_pModel->getChannel(i)->reconstructBuffer();
+        m_pModel->updateViewAndOffscreens();
+
+        if (m_pModel->getRSync()->isServer())
+        {
+            QDomDocument doc;
+            doc.appendChild(domElement("Screen", doc));
+            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCREEN, doc.toString(0));
+        }
+    }
+}
+
+/**
+ * Draw the screen shape object with.
+ *
+ * @param bDepthMaskControl True to use glDepthMask() for blending.
+ */
+void Screen::draw(bool bDepthMaskControl)
+{
+    glPushMatrix();
+
+    glMultMatrixf(m_transformMatrix.getMatrix().getData());
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    // setup rendering parameters
+    glColor4d(0.5, 0.5, 0.5, 0.5);
+    glEnable(GL_BLEND);
+    if (bDepthMaskControl)
+        glDepthMask(false);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glEnable(GL_LIGHTING);
+
+    // render the screen without textures
+    m_pCurrentShape->draw(false);
+    if (bDepthMaskControl)
+        glDepthMask(true);
+
+    glPopAttrib();
+
+    glPopMatrix();
+}
+
+/**
+ * Draw the wire frame mesh of the screen.
+ */
+void Screen::drawFrame()
+{
+    glPushMatrix();
+
+    glMultMatrixf(m_transformMatrix.getMatrix().getData());
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    // draw overlay meshs
+    if (m_bShowFrame)
+    {
+        // setup rendering parameters
+        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+        glDisable(GL_LIGHTING);
+        glDisable(GL_TEXTURE_2D);
+        glEnable(GL_POLYGON_OFFSET_LINE);
+        glLineWidth(m_frameLineWidth);
+        glPolygonOffset(-1.0, -1.0);
+
+        glColor4d(1.0, 1.0, 1.0, 1.0);
+        m_pCurrentShape->draw(true);
+
+        glDisable(GL_POLYGON_OFFSET_LINE);
+        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    }
+
+    glPopAttrib();
+
+    glPopMatrix();
+}
+
+/**
+ * Draw the screen object with projection texture image of the specified channel.
+ *
+ * @param source Projection image source to draw.
+ * @param pChannel Channel which draws for.
+ */
+void Screen::draw(PROJECT_SOURCE source, Channel* pChannel)
+{
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    glMultMatrixf(m_transformMatrix.getMatrix().getData());
+
+    // setup rendering parameters
+    glEnable(GL_BLEND);
+    glDepthMask(false);
+    glDisable(GL_LIGHTING);
+    if (source != PROJECT_SOURCE_EXPORT_BLENDING)
+    {
+        glBlendFunc(GL_ONE, GL_ONE);
+        glColor4d(0.0, 0.0, 0.0, 1.0);
+    }
+
+    // setup common projection texture parameters
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_GEN_S);
+    glEnable(GL_TEXTURE_GEN_T);
+    glEnable(GL_TEXTURE_GEN_R);
+    glEnable(GL_TEXTURE_GEN_Q);
+
+    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+
+    static const GLdouble genfunc[][4] = {
+        { 1.0, 0.0, 0.0, 0.0 },
+        { 0.0, 1.0, 0.0, 0.0 },
+        { 0.0, 0.0, 1.0, 0.0 },
+        { 0.0, 0.0, 0.0, 1.0 },
+    };
+    glTexGendv(GL_S, GL_EYE_PLANE, genfunc[0]);
+    glTexGendv(GL_T, GL_EYE_PLANE, genfunc[1]);
+    glTexGendv(GL_R, GL_EYE_PLANE, genfunc[2]);
+    glTexGendv(GL_Q, GL_EYE_PLANE, genfunc[3]);
+
+    // prepare a projection matrix to use depends on the projection source
+    TransformMatrix xformMat;
+    if (source == PROJECT_SOURCE_PROJECTORAREA ||
+        source == PROJECT_SOURCE_EXPORT_BLENDING)
+    {
+		xformMat = pChannel->getProjectorTransformMatrix();
+    }
+    else
+    {
+		xformMat = pChannel->getView()->getTransformMatrix();
+    }
+
+    // setup clip plane to hide opposite side projection
+#if 1
+    if (m_pCurrentShape->isClippingRequired())
+    {
+        Vec3f pos = makeTrans<Vec3f>(xformMat.getMatrix());
+        Vec3f planeAxis = m_transformMatrix.getMatrix() * (xformMat.getMatrix()) * Vec3f(0.0f, 0.0f, -1.0f);
+        GLdouble plane[4] = { planeAxis[0], planeAxis[1], planeAxis[2], -dot(pos, planeAxis) };
+        glClipPlane(GL_CLIP_PLANE0, plane);
+        glEnable(GL_CLIP_PLANE0);
+    }
+#endif // 1
+
+    // bind a texture for projection
+    switch (source)
+    {
+    case PROJECT_SOURCE_PROJECTORAREA:
+        glBindTexture(GL_TEXTURE_2D, m_pModel->getProjectorAreaTexture()); break;
+    case PROJECT_SOURCE_VIEWAREA:
+        glBindTexture(GL_TEXTURE_2D, m_pModel->getViewAreaTexture()); break;
+    case PROJECT_SOURCE_SCENE:
+        glBindTexture(GL_TEXTURE_2D, pChannel->getViewTexture()); break;
+    case PROJECT_SOURCE_EXPORT_DISTORTION:
+        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getTexCoordColorTexture()); break;
+    case PROJECT_SOURCE_EXPORT_DISTORTION_R:
+        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getTexCoordColorRTexture()); break;
+    case PROJECT_SOURCE_EXPORT_BLENDING:
+        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getBlendingAreaTexture());
+        break;
+    case PROJECT_SOURCE_NONE:
+        break;
+    }
+
+    // setup texture parameters
+    if (source != PROJECT_SOURCE_EXPORT_BLENDING)
+        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+    else
+        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+    GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
+
+    if (source != PROJECT_SOURCE_EXPORT_DISTORTION) {
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812D); // GL_CLAMP_TO_BORDER
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812D); // GL_CLAMP_TO_BORDER
+    } else {
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    }
+
+    switch (source)
+    {
+    case PROJECT_SOURCE_PROJECTORAREA:
+    case PROJECT_SOURCE_EXPORT_DISTORTION:
+    case PROJECT_SOURCE_EXPORT_DISTORTION_R:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        break;
+    default:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        break;
+    }
+
+    // setup texture projection matrix
+    glMatrixMode(GL_TEXTURE);
+    glPushMatrix();
+    glLoadIdentity();
+
+    if (source != PROJECT_SOURCE_EXPORT_DISTORTION)
+    {
+        glTranslated(0.5, 0.5, 1.0);
+        glScaled(0.5, 0.5, 1.0);
+    } else {
+	    glScaled(0.5, 0.5, 1.0);
+    	glScaled(16.0, 16.0, 1.0);
+    }
+
+	if (source == PROJECT_SOURCE_PROJECTORAREA ||
+        source == PROJECT_SOURCE_EXPORT_BLENDING)
+    {
+		pChannel->getProjector()->beginProjection();
+    }
+    else
+    {
+		ProjectionMatrix projMat = pChannel->getView()->getProjectionMatrix();
+		glMultMatrixf(projMat.getMatrix());
+    }
+
+    Matrix44f invXformMat = xformMat.getMatrix();
+    invert(invXformMat);
+	glMultMatrixf(invXformMat.getData());
+
+    glMultMatrixf(m_transformMatrix.getMatrix().getData());
+
+    glMatrixMode(GL_MODELVIEW);
+
+    // render the screen with the projected texture
+    m_pCurrentShape->draw(false);
+
+#if 1
+	if (source == PROJECT_SOURCE_PROJECTORAREA ||
+        source == PROJECT_SOURCE_EXPORT_BLENDING)
+    {
+		pChannel->getProjector()->endProjection();
+    }
+#endif
+
+    if (m_pCurrentShape->isClippingRequired())
+        glDisable(GL_CLIP_PLANE0);
+
+    glMatrixMode(GL_TEXTURE);
+    glPopMatrix();
+
+    glMatrixMode(GL_MODELVIEW);
+
+    glDisable(GL_TEXTURE_GEN_S);
+    glDisable(GL_TEXTURE_GEN_T);
+    glDisable(GL_TEXTURE_GEN_R);
+    glDisable(GL_TEXTURE_GEN_Q);
+    glDisable(GL_TEXTURE_2D);
+
+    glDepthMask(true);
+
+    glPopAttrib();
+
+    glPopMatrix();
+}
+
+/**
+ * Notify to redraw the screen.
+ */
+void Screen::notifyRedraw()
+{
+    m_pModel->updateViews();
+
+    if (m_pModel->getRSync()->isServer())
+    {
+        QDomDocument doc;
+        doc.appendChild(domElement("Screen", doc));
+        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCREEN, doc.toString(0));
+    }
+}
+
+/**
+ * Restore the screen shape from XML data.
+ *
+ * @param element Parent XML element of the screen data.
+ */
+bool Screen::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix"));
+        setCurrentShape(element.attribute("shapeName"));
+        m_bShowFrame = element.attribute("showFrame").toLower()=="true";
+        m_frameLineWidth = element.attribute("frameLineWidth").toFloat();
+        setBufferSize(element.attribute("bufferWidth").toInt(), element.attribute("bufferHeight").toInt());
+
+        QDomElement shapes = element.firstChildElement("Shapes");
+        QDomElement shape = shapes.firstChild().toElement();
+        while (!shape.isNull())
+		{
+            if (shape.tagName() == "Shape") {
+                ScreenShape* pShape = getShape(shape.attribute("name"));
+				if (pShape)
+                    if( !pShape->initFromDOMElement(shape) )
+						return false;
+            }
+            shape = shape.nextSiblingElement();
+        }
+    }
+
+    notifyRedraw();
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current screen shape as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen data as XML data.
+ */
+QDomElement Screen::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc));
+    de.setAttribute("shapeName", getCurrentShapeName());
+    de.setAttribute("showFrame", (m_bShowFrame?"true":"false"));
+    de.setAttribute("frameLineWidth", m_frameLineWidth);
+    de.setAttribute("bufferWidth", QString::number(m_bufferWidth));
+    de.setAttribute("bufferHeight", QString::number(m_bufferHeight));
+
+    QDomElement shapes = doc.createElement("Shapes");
+    for (int i=0; i<m_pShapes.size(); ++i)
+        shapes.appendChild(m_pShapes[i]->domElement("Shape", doc));
+    de.appendChild(shapes);
+
+    return de;
+}
+
+void Screen::reset()
+{
+    m_pCurrentShape = m_pShapes[0];	// Dome
+    m_bShowFrame = true;
+    m_frameLineWidth = 1.0f;
+    m_bufferWidth = 256;
+    m_bufferHeight = 256;
+}
Index: projectionDesigner/trunk/projdesigner/src/Version.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Version.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Version.cpp	(revision 4)
@@ -0,0 +1,52 @@
+#include <QString>
+#include <QDebug>
+#include <QStringList>
+#include "Version.h"
+
+QString version_major(const QString& version) {return version.split(".")[0];}
+QString version_minor(const QString& version) {return version.split(".")[1];}
+QString version_micro(const QString& version) {return version.split(".")[2];}
+QString version_nano(const QString& version)  {return version.split(".")[3];}
+
+/** returns true if v1 is less than v2. */
+bool version_lt(const QString& v1, const QString& v2)
+{
+		if (version_major(v1).toInt()<version_major(v2).toInt()) return true;
+		if (version_major(v1).toInt()>version_major(v2).toInt()) return false;
+		if (version_minor(v1).toInt()<version_minor(v2).toInt()) return true;
+		if (version_minor(v1).toInt()>version_minor(v2).toInt()) return false;
+		if (version_micro(v1).toInt()<version_micro(v2).toInt()) return true;
+		if (version_micro(v1).toInt()>version_micro(v2).toInt()) return false;
+		if (version_nano(v1).toInt()<version_nano(v2).toInt()) return true;
+		if (version_nano(v1).toInt()>version_nano(v2).toInt()) return false;
+		return false;
+}
+
+/** returns true if v1 equal v2. */
+bool version_eq(const QString& v1, const QString& v2)
+{
+		return 
+				version_major(v1)==version_major(v2)
+				&& version_minor(v1)==version_minor(v2)
+				&& version_micro(v1)==version_micro(v2)
+				&& version_nano(v1)==version_nano(v2);
+}
+
+/** returns true if v1 is less than or equal v2. */
+bool version_le(const QString& v1, const QString& v2)
+{
+		return version_lt(v1, v2) || version_eq(v1, v2);
+}
+
+/** returns true if v1 is greater than or equal v2. */
+bool version_ge(const QString& v1, const QString& v2)
+{
+		return !version_lt(v1, v2);
+}
+
+/** returns true if v1 is greater than v2. */
+bool version_gt(const QString& v1, const QString& v2)
+{
+		return !version_le(v1, v2);
+}
+
Index: projectionDesigner/trunk/projdesigner/src/Warp.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/Warp.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/Warp.cpp	(revision 4)
@@ -0,0 +1,300 @@
+#include <math.h>
+
+#include "Warp.h"
+
+using namespace projection;
+
+Warp::Warp()
+{
+    m_bEnabled = true;
+    m_pCtrlPoints = NULL;
+    setNumCtrlPoints(4);
+    m_gridSize = 24;
+    m_zoom = 1.0f;
+    m_selectedCtrlPoint = -1;
+    m_bShowCtrlPoints = true;
+}
+
+Warp::~Warp()
+{
+}
+
+void Warp::draw(bool bForExport, bool bForBlend)
+{
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+
+    glGetIntegerv(GL_VIEWPORT, m_viewport);
+
+    glOrtho(-0.5f, 0.5f, -0.5f, 0.5f, -1.0f, 1.0f);
+    glGetDoublev(GL_PROJECTION_MATRIX, m_projMatrix);
+
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    if (!bForExport)
+        glScalef(m_zoom, m_zoom, 1.0f);
+    glGetDoublev(GL_MODELVIEW_MATRIX, m_modelMatrix);
+
+    glDisable(GL_LIGHTING);
+    glColor3f(1.0, 1.0, 1.0);
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_MAP2_VERTEX_3);
+    glEnable(GL_MAP2_TEXTURE_COORD_2);
+    glMapGrid2f(m_gridSize, 0.0f, 1.0f, m_gridSize, 0.0f, 1.0f);
+    glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, m_numCtrlPoints, 0, 1, m_numCtrlPoints * 3, m_numCtrlPoints, m_pCtrlPoints);
+    GLfloat pTexCoords[2][2][2] = {
+        {{0.0f, 0.0f}, {1.0f, 0.0f}},
+        {{0.0f, 1.0f}, {1.0f, 1.0f}}};
+    glMap2f(GL_MAP2_TEXTURE_COORD_2, 0.0f, 1.0f, 2, 2, 0.0f, 1.0f, 4, 2, &pTexCoords[0][0][0]);
+    glEvalMesh2(GL_FILL, 0, m_gridSize, 0, m_gridSize);
+
+    if (m_bShowCtrlPoints && !bForExport)
+    {
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_DEPTH_TEST);
+
+        glLineWidth(1.0f);
+        for (int y=0; y<m_numCtrlPoints; ++y)
+        {
+            for (int x=0; x<m_numCtrlPoints; ++x)
+            {
+                float dx = 1.0f / (m_numCtrlPoints-1) * (float)x - 0.5f;
+                float dy = 1.0f / (m_numCtrlPoints-1) * (float)y - 0.5f;
+                if (m_selectedCtrlPoint == y*m_numCtrlPoints+x)
+                    glColor3f(0.0f, 1.0f, 0.0f);
+                else
+                {
+                    if (bForBlend)
+                        glColor3f(0.0f, 0.0f, 1.0f);
+                    else
+                        glColor3f(1.0f, 1.0f, 1.0f);
+                }
+                glBegin(GL_LINES);
+                glVertex3f(dx, dy, 0.0f);
+                glVertex3fv(&m_pCtrlPoints[(y*m_numCtrlPoints+x)*3]);
+                glEnd();
+            }
+        }
+
+        glPointSize(6.0f);
+        glColor3f(1.0f, 1.0f, 0.0f);
+        glBegin(GL_POINTS);
+        for (int i=0; i<m_numCtrlPoints*m_numCtrlPoints; ++i) {
+            if (i != m_selectedCtrlPoint)
+                glVertex3fv(&m_pCtrlPoints[i*3]);
+        }
+        glEnd();
+        if (m_selectedCtrlPoint >= 0)
+        {
+            glColor3f(1.0f, 0.0f, 0.0f);
+            glBegin(GL_POINTS);
+            glVertex3fv(&m_pCtrlPoints[m_selectedCtrlPoint*3]);
+            glEnd();
+        }
+    }
+
+    glPopMatrix();
+
+    glPopAttrib();
+}
+
+bool Warp::pick(int x, int y)
+{
+    if (!m_bEnabled)
+        return 0;
+
+    m_lastMouseX = x;
+    m_lastMouseY = y;
+
+    int newCtrlPoint = pickCtrlPoint(x, y);
+    if (newCtrlPoint != m_selectedCtrlPoint && newCtrlPoint >= 0)
+    {
+        m_selectedCtrlPoint = newCtrlPoint;
+        return true;
+    }
+    return false;
+}
+
+bool Warp::drag(int x, int y)
+{
+    if (!m_bEnabled)
+        return 0;
+
+    if (m_selectedCtrlPoint < 0)
+        return false;
+
+    GLdouble objx, objy, objz;
+    GLdouble objx2, objy2, objz2;
+
+    gluUnProject(x - m_lastMouseX, -(y - m_lastMouseY), 0.95,
+                 m_modelMatrix, m_projMatrix, m_viewport,
+                 &objx, &objy, &objz);
+    gluUnProject(0, 0, 0.95,
+                 m_modelMatrix, m_projMatrix, m_viewport,
+                 &objx2, &objy2, &objz2);
+    m_pCtrlPoints[m_selectedCtrlPoint * 3 + 0] += objx-objx2;
+    m_pCtrlPoints[m_selectedCtrlPoint * 3 + 1] += objy-objy2;
+
+    m_lastMouseX = x;
+    m_lastMouseY = y;
+
+    return true;
+}
+
+void Warp::setEnabled(bool bEnabled)
+{
+    m_bEnabled = bEnabled;
+}
+
+bool Warp::getEnabled() const
+{
+    return m_bEnabled;
+}
+
+void Warp::setNumCtrlPoints(int num)
+{
+    if (num == 0)
+        return;
+
+    if (num > 8)
+        num = 8;
+    if (num <2)
+        num = 2;
+
+    if (m_pCtrlPoints)
+        delete [] m_pCtrlPoints;
+    m_numCtrlPoints = num;
+    m_pCtrlPoints = new float[num*num*3];
+    reset();
+}
+
+int Warp::getNumCtrlPoints() const
+{
+    return m_numCtrlPoints;
+}
+
+void Warp::setZoom(float zoom)
+{
+    m_zoom = zoom;
+}
+
+float Warp::getZoom() const
+{
+    return m_zoom;
+}
+
+void Warp::setGridSize(int gridSize)
+{
+    m_gridSize = gridSize;
+}
+
+int Warp::getGridSize() const
+{
+    return m_gridSize;
+}
+
+void Warp::setShowCtrlPoints(bool bShow)
+{
+    m_bShowCtrlPoints = bShow;
+}
+
+bool Warp::getShowCtrlPoints() const
+{
+    return m_bShowCtrlPoints;
+}
+
+void Warp::reset()
+{
+    for (int y=0; y<m_numCtrlPoints; ++y) {
+        for (int x=0; x<m_numCtrlPoints; ++x) {
+            m_pCtrlPoints[(y*m_numCtrlPoints+x)*3+0] = 1.0f / (m_numCtrlPoints-1) * (float)x - 0.5f;
+            m_pCtrlPoints[(y*m_numCtrlPoints+x)*3+1] = 1.0f / (m_numCtrlPoints-1) * (float)y - 0.5f;
+            m_pCtrlPoints[(y*m_numCtrlPoints+x)*3+2] = 0.0f;
+        }
+    }
+}
+
+int Warp::pickCtrlPoint(float x, float y)
+{
+    int hits;
+
+    GLuint selectBuffer[64];
+    glSelectBuffer(sizeof(selectBuffer), selectBuffer);
+
+    glRenderMode(GL_SELECT);
+    glInitNames();
+    glPushName(~0);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPickMatrix(x, m_viewport[3] - y, 8.0, 8.0, m_viewport);
+    glMultMatrixd(m_projMatrix);
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    glMultMatrixd(m_modelMatrix);
+    for (int i=0; i<m_numCtrlPoints*m_numCtrlPoints; ++i) {
+        glLoadName(i);
+        glBegin(GL_POINTS);
+        glVertex3fv(&m_pCtrlPoints[i*3]);
+        glEnd();
+    }
+    glPopMatrix();
+    hits = glRenderMode(GL_RENDER);
+
+    if (hits)
+        return selectBuffer[3];
+    return ~0;
+}
+
+/**
+ * Restore the channel data from XML data.
+ *
+ * @param element Parent XML element of the warp data.
+ */
+void Warp::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        m_bEnabled = (element.attribute("enabled")=="true");
+        int numCtrlPoints = (int)sqrtf(element.attribute("numCtrlPoints").toInt());
+        if (numCtrlPoints != m_numCtrlPoints)
+            setNumCtrlPoints(numCtrlPoints);
+
+        int count = 0;
+        QDomElement ctrlPointElem = element.firstChildElement("ctrlPoint");
+        while (!ctrlPointElem.isNull()) {
+            if (count >= m_numCtrlPoints * m_numCtrlPoints)
+                break;
+            m_pCtrlPoints[count*3+0] = ctrlPointElem.attribute("x").toDouble();
+            m_pCtrlPoints[count*3+1] = ctrlPointElem.attribute("y").toDouble();
+            m_pCtrlPoints[count*3+2] = 0.0f;
+            ctrlPointElem = ctrlPointElem.nextSiblingElement("ctrlPoint");
+            count++;
+        }
+    }
+}
+
+/**
+ * Store the current warp data as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current warp data as XML data.
+ */
+QDomElement Warp::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.setAttribute("enabled", m_bEnabled?"true":"false");
+    de.setAttribute("numCtrlPoints", m_numCtrlPoints*m_numCtrlPoints);
+    for (int i=0; i<m_numCtrlPoints*m_numCtrlPoints; ++i) {
+        QDomElement ctrlPointElem = doc.createElement("ctrlPoint");
+        ctrlPointElem.setAttribute("x", m_pCtrlPoints[i*3+0]);
+        ctrlPointElem.setAttribute("y", m_pCtrlPoints[i*3+1]);
+        de.appendChild(ctrlPointElem);
+    }
+
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/glm/glm.c
===================================================================
--- projectionDesigner/trunk/projdesigner/src/glm/glm.c	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/glm/glm.c	(revision 4)
@@ -0,0 +1,1910 @@
+/*    
+      glm.c
+      Nate Robins, 1997, 2000
+      nate@pobox.com, http://www.pobox.com/~nate
+ 
+      Wavefront OBJ model file format reader/writer/manipulator.
+
+      Includes routines for generating smooth normals with
+      preservation of edges, welding redundant vertices & texture
+      coordinate generation (spheremap and planar projections) + more.
+  
+*/
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "glm/glm.h"
+
+
+#define T(x) (model->triangles[(x)])
+
+
+/* _GLMnode: general purpose node */
+typedef struct _GLMnode {
+    GLuint         index;
+    GLboolean      averaged;
+    struct _GLMnode* next;
+} GLMnode;
+
+
+/* glmMax: returns the maximum of two floats */
+static GLfloat
+glmMax(GLfloat a, GLfloat b) 
+{
+    if (b > a)
+        return b;
+    return a;
+}
+
+/* glmAbs: returns the absolute value of a float */
+static GLfloat
+glmAbs(GLfloat f)
+{
+    if (f < 0)
+        return -f;
+    return f;
+}
+
+/* glmDot: compute the dot product of two vectors
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3])
+ */
+static GLfloat
+glmDot(GLfloat* u, GLfloat* v)
+{
+    assert(u); assert(v);
+    
+    return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
+}
+
+/* glmCross: compute the cross product of two vectors
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3])
+ * n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in
+ */
+static GLvoid
+glmCross(GLfloat* u, GLfloat* v, GLfloat* n)
+{
+    assert(u); assert(v); assert(n);
+    
+    n[0] = u[1]*v[2] - u[2]*v[1];
+    n[1] = u[2]*v[0] - u[0]*v[2];
+    n[2] = u[0]*v[1] - u[1]*v[0];
+}
+
+/* glmNormalize: normalize a vector
+ *
+ * v - array of 3 GLfloats (GLfloat v[3]) to be normalized
+ */
+static GLvoid
+glmNormalize(GLfloat* v)
+{
+    GLfloat l;
+    
+    assert(v);
+    
+    l = (GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+    v[0] /= l;
+    v[1] /= l;
+    v[2] /= l;
+}
+
+/* glmEqual: compares two vectors and returns GL_TRUE if they are
+ * equal (within a certain threshold) or GL_FALSE if not. An epsilon
+ * that works fairly well is 0.000001.
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3]) 
+ */
+static GLboolean
+glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon)
+{
+    if (glmAbs(u[0] - v[0]) < epsilon &&
+        glmAbs(u[1] - v[1]) < epsilon &&
+        glmAbs(u[2] - v[2]) < epsilon) 
+    {
+        return GL_TRUE;
+    }
+    return GL_FALSE;
+}
+
+/* glmWeldVectors: eliminate (weld) vectors that are within an
+ * epsilon of each other.
+ *
+ * vectors     - array of GLfloat[3]'s to be welded
+ * numvectors - number of GLfloat[3]'s in vectors
+ * epsilon     - maximum difference between vectors 
+ *
+ */
+GLfloat*
+glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon)
+{
+    GLfloat* copies;
+    GLuint   copied;
+    GLuint   i, j;
+    
+    copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
+    memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
+    
+    copied = 1;
+    for (i = 1; i <= *numvectors; i++) {
+        for (j = 1; j <= copied; j++) {
+            if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
+                goto duplicate;
+            }
+        }
+        
+        /* must not be any duplicates -- add to the copies array */
+        copies[3 * copied + 0] = vectors[3 * i + 0];
+        copies[3 * copied + 1] = vectors[3 * i + 1];
+        copies[3 * copied + 2] = vectors[3 * i + 2];
+        j = copied;             /* pass this along for below */
+        copied++;
+        
+duplicate:
+/* set the first component of this vector to point at the correct
+        index into the new copies array */
+        vectors[3 * i + 0] = (GLfloat)j;
+    }
+    
+    *numvectors = copied-1;
+    return copies;
+}
+
+/* glmFindGroup: Find a group in the model */
+GLMgroup*
+glmFindGroup(GLMmodel* model, char* name)
+{
+    GLMgroup* group;
+    
+    assert(model);
+    
+    group = model->groups;
+    while(group) {
+        if (!strcmp(name, group->name))
+            break;
+        group = group->next;
+    }
+    
+    return group;
+}
+
+/* glmAddGroup: Add a group to the model */
+GLMgroup*
+glmAddGroup(GLMmodel* model, char* name)
+{
+    GLMgroup* group;
+    
+    group = glmFindGroup(model, name);
+    if (!group) {
+        group = (GLMgroup*)malloc(sizeof(GLMgroup));
+        group->name = strdup(name);
+        group->material = 0;
+        group->numtriangles = 0;
+        group->triangles = NULL;
+        group->next = model->groups;
+        model->groups = group;
+        model->numgroups++;
+    }
+    
+    return group;
+}
+
+/* glmFindGroup: Find a material in the model */
+GLuint
+glmFindMaterial(GLMmodel* model, char* name)
+{
+    GLuint i;
+    
+    /* XXX doing a linear search on a string key'd list is pretty lame,
+    but it works and is fast enough for now. */
+    for (i = 0; i < model->nummaterials; i++) {
+        if (!strcmp(model->materials[i].name, name))
+            goto found;
+    }
+    
+    /* didn't find the name, so print a warning and return the default
+    material (0). */
+    printf("glmFindMaterial():  can't find material \"%s\".\n", name);
+    i = 0;
+    
+found:
+    return i;
+}
+
+
+/* glmDirName: return the directory given a path
+ *
+ * path - filesystem path
+ *
+ * NOTE: the return value should be free'd.
+ */
+static char*
+glmDirName(char* path)
+{
+    char* dir;
+    char* s;
+    
+    dir = strdup(path);
+    
+    s = strrchr(dir, '/');
+    if (s)
+        s[1] = '\0';
+    else
+        dir[0] = '\0';
+    
+    return dir;
+}
+
+
+/* glmReadMTL: read a wavefront material library file
+ *
+ * model - properly initialized GLMmodel structure
+ * name  - name of the material library
+ */
+static GLvoid
+glmReadMTL(GLMmodel* model, char* name)
+{
+    FILE* file;
+    char* dir;
+    char* filename;
+    char    buf[128];
+    GLuint nummaterials, i;
+    
+    dir = glmDirName(model->pathname);
+    filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
+    strcpy(filename, dir);
+    strcat(filename, name);
+    free(dir);
+    
+    file = fopen(filename, "r");
+    if (!file) {
+        fprintf(stderr, "glmReadMTL() failed: can't open material file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    free(filename);
+    
+    /* count the number of materials in the file */
+    nummaterials = 1;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'n':               /* newmtl */
+            fgets(buf, sizeof(buf), file);
+            nummaterials++;
+            sscanf(buf, "%s %s", buf, buf);
+            break;
+        default:
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        }
+    }
+    
+    rewind(file);
+    
+    model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
+    model->nummaterials = nummaterials;
+    
+    /* set the default material */
+    for (i = 0; i < nummaterials; i++) {
+        model->materials[i].name = NULL;
+        model->materials[i].shininess = 65.0;
+        model->materials[i].diffuse[0] = 0.8f;
+        model->materials[i].diffuse[1] = 0.8f;
+        model->materials[i].diffuse[2] = 0.8f;
+        model->materials[i].diffuse[3] = 1.0;
+        model->materials[i].ambient[0] = 0.2f;
+        model->materials[i].ambient[1] = 0.2f;
+        model->materials[i].ambient[2] = 0.2f;
+        model->materials[i].ambient[3] = 1.0;
+        model->materials[i].specular[0] = 0.0;
+        model->materials[i].specular[1] = 0.0;
+        model->materials[i].specular[2] = 0.0;
+        model->materials[i].specular[3] = 1.0;
+    }
+    model->materials[0].name = strdup("default");
+    
+    /* now, read in the data */
+    nummaterials = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'n':               /* newmtl */
+            fgets(buf, sizeof(buf), file);
+            sscanf(buf, "%s %s", buf, buf);
+            nummaterials++;
+            model->materials[nummaterials].name = strdup(buf);
+            break;
+        case 'N':
+            fscanf(file, "%f", &model->materials[nummaterials].shininess);
+            /* wavefront shininess is from [0, 1000], so scale for OpenGL */
+            model->materials[nummaterials].shininess /= 1000.0;
+            model->materials[nummaterials].shininess *= 128.0;
+            break;
+        case 'K':
+            switch(buf[1]) {
+            case 'd':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].diffuse[0],
+                    &model->materials[nummaterials].diffuse[1],
+                    &model->materials[nummaterials].diffuse[2]);
+                break;
+            case 's':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].specular[0],
+                    &model->materials[nummaterials].specular[1],
+                    &model->materials[nummaterials].specular[2]);
+                break;
+            case 'a':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].ambient[0],
+                    &model->materials[nummaterials].ambient[1],
+                    &model->materials[nummaterials].ambient[2]);
+                break;
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+            }
+            break;
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+        }
+    }
+
+    fclose(file);
+}
+
+/* glmWriteMTL: write a wavefront material library file
+ *
+ * model   - properly initialized GLMmodel structure
+ * modelpath  - pathname of the model being written
+ * mtllibname - name of the material library to be written
+ */
+static GLvoid
+glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname)
+{
+    FILE* file;
+    char* dir;
+    char* filename;
+    GLMmaterial* material;
+    GLuint i;
+    
+    dir = glmDirName(modelpath);
+    filename = (char*)malloc(sizeof(char) * (strlen(dir)+strlen(mtllibname)));
+    strcpy(filename, dir);
+    strcat(filename, mtllibname);
+    free(dir);
+    
+    /* open the file */
+    file = fopen(filename, "w");
+    if (!file) {
+        fprintf(stderr, "glmWriteMTL() failed: can't open file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    free(filename);
+    
+    /* spit out a header */
+    fprintf(file, "#  \n");
+    fprintf(file, "#  Wavefront MTL generated by GLM library\n");
+    fprintf(file, "#  \n");
+    fprintf(file, "#  GLM library\n");
+    fprintf(file, "#  Nate Robins\n");
+    fprintf(file, "#  ndr@pobox.com\n");
+    fprintf(file, "#  http://www.pobox.com/~ndr\n");
+    fprintf(file, "#  \n\n");
+    
+    for (i = 0; i < model->nummaterials; i++) {
+        material = &model->materials[i];
+        fprintf(file, "newmtl %s\n", material->name);
+        fprintf(file, "Ka %f %f %f\n", 
+            material->ambient[0], material->ambient[1], material->ambient[2]);
+        fprintf(file, "Kd %f %f %f\n", 
+            material->diffuse[0], material->diffuse[1], material->diffuse[2]);
+        fprintf(file, "Ks %f %f %f\n", 
+            material->specular[0],material->specular[1],material->specular[2]);
+        fprintf(file, "Ns %f\n", material->shininess / 128.0 * 1000.0);
+        fprintf(file, "\n");
+    }
+}
+
+
+/* glmFirstPass: first pass at a Wavefront OBJ file that gets all the
+ * statistics of the model (such as #vertices, #normals, etc)
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static GLvoid
+glmFirstPass(GLMmodel* model, FILE* file) 
+{
+    GLuint  numvertices;        /* number of vertices in model */
+    GLuint  numnormals;         /* number of normals in model */
+    GLuint  numtexcoords;       /* number of texcoords in model */
+    GLuint  numtriangles;       /* number of triangles in model */
+    GLMgroup* group;            /* current group */
+    unsigned    v, n, t;
+    char        buf[128];
+    
+    /* make a default group */
+    group = glmAddGroup(model, "default");
+    
+    numvertices = numnormals = numtexcoords = numtriangles = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'v':               /* v, vn, vt */
+            switch(buf[1]) {
+            case '\0':          /* vertex */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numvertices++;
+                break;
+            case 'n':           /* normal */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numnormals++;
+                break;
+            case 't':           /* texcoord */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numtexcoords++;
+                break;
+            default:
+                printf("glmFirstPass(): Unknown token \"%s\".\n", buf);
+                exit(1);
+                break;
+            }
+            break;
+            case 'm':
+                fgets(buf, sizeof(buf), file);
+                sscanf(buf, "%s %s", buf, buf);
+                model->mtllibname = strdup(buf);
+                glmReadMTL(model, buf);
+                break;
+            case 'u':
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+            case 'g':               /* group */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+#if SINGLE_STRING_GROUP_NAMES
+                sscanf(buf, "%s", buf);
+#else
+                buf[strlen(buf)-1] = '\0';  /* nuke '\n' */
+#endif
+                group = glmAddGroup(model, buf);
+                break;
+            case 'f':               /* face */
+                v = n = t = 0;
+                fscanf(file, "%s", buf);
+                /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+                if (strstr(buf, "//")) {
+                    /* v//n */
+                    sscanf(buf, "%d//%d", &v, &n);
+                    fscanf(file, "%d//%d", &v, &n);
+                    fscanf(file, "%d//%d", &v, &n);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d//%d", &v, &n) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
+                    /* v/t/n */
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+                    /* v/t */
+                    fscanf(file, "%d/%d", &v, &t);
+                    fscanf(file, "%d/%d", &v, &t);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d/%d", &v, &t) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else {
+                    /* v */
+                    fscanf(file, "%d", &v);
+                    fscanf(file, "%d", &v);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d", &v) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                }
+                break;
+                
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+        }
+  }
+  
+  /* set the stats in the model structure */
+  model->numvertices  = numvertices;
+  model->numnormals   = numnormals;
+  model->numtexcoords = numtexcoords;
+  model->numtriangles = numtriangles;
+  
+  /* allocate memory for the triangles in each group */
+  group = model->groups;
+  while(group) {
+      group->triangles = (GLuint*)malloc(sizeof(GLuint) * group->numtriangles);
+      group->numtriangles = 0;
+      group = group->next;
+  }
+}
+
+/* glmSecondPass: second pass at a Wavefront OBJ file that gets all
+ * the data.
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static GLvoid
+glmSecondPass(GLMmodel* model, FILE* file) 
+{
+    GLuint  numvertices;        /* number of vertices in model */
+    GLuint  numnormals;         /* number of normals in model */
+    GLuint  numtexcoords;       /* number of texcoords in model */
+    GLuint  numtriangles;       /* number of triangles in model */
+    GLfloat*    vertices;           /* array of vertices  */
+    GLfloat*    normals;            /* array of normals */
+    GLfloat*    texcoords;          /* array of texture coordinates */
+    GLMgroup* group;            /* current group pointer */
+    GLuint  material;           /* current material */
+    GLuint  v, n, t;
+    char        buf[128];
+    
+    /* set the pointer shortcuts */
+    vertices       = model->vertices;
+    normals    = model->normals;
+    texcoords    = model->texcoords;
+    group      = model->groups;
+    
+    /* on the second pass through the file, read all the data into the
+    allocated arrays */
+    numvertices = numnormals = numtexcoords = 1;
+    numtriangles = 0;
+    material = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'v':               /* v, vn, vt */
+            switch(buf[1]) {
+            case '\0':          /* vertex */
+                fscanf(file, "%f %f %f", 
+                    &vertices[3 * numvertices + 0], 
+                    &vertices[3 * numvertices + 1], 
+                    &vertices[3 * numvertices + 2]);
+                numvertices++;
+                break;
+            case 'n':           /* normal */
+                fscanf(file, "%f %f %f", 
+                    &normals[3 * numnormals + 0],
+                    &normals[3 * numnormals + 1], 
+                    &normals[3 * numnormals + 2]);
+                numnormals++;
+                break;
+            case 't':           /* texcoord */
+                fscanf(file, "%f %f", 
+                    &texcoords[2 * numtexcoords + 0],
+                    &texcoords[2 * numtexcoords + 1]);
+                numtexcoords++;
+                break;
+            }
+            break;
+            case 'u':
+                fgets(buf, sizeof(buf), file);
+                sscanf(buf, "%s %s", buf, buf);
+                group->material = material = glmFindMaterial(model, buf);
+                break;
+            case 'g':               /* group */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+#if SINGLE_STRING_GROUP_NAMES
+                sscanf(buf, "%s", buf);
+#else
+                buf[strlen(buf)-1] = '\0';  /* nuke '\n' */
+#endif
+                group = glmFindGroup(model, buf);
+                group->material = material;
+                break;
+            case 'f':               /* face */
+                v = n = t = 0;
+                fscanf(file, "%s", buf);
+                /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+                if (strstr(buf, "//")) {
+                    /* v//n */
+                    sscanf(buf, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).nindices[0] = n;
+                    fscanf(file, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).nindices[1] = n;
+                    fscanf(file, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).nindices[2] = n;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d//%d", &v, &n) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).nindices[2] = n;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
+                    /* v/t/n */
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).tindices[0] = t;
+                    T(numtriangles).nindices[0] = n;
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).tindices[1] = t;
+                    T(numtriangles).nindices[1] = n;
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).tindices[2] = t;
+                    T(numtriangles).nindices[2] = n;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+                        T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+                        T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).tindices[2] = t;
+                        T(numtriangles).nindices[2] = n;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+                    /* v/t */
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).tindices[0] = t;
+                    fscanf(file, "%d/%d", &v, &t);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).tindices[1] = t;
+                    fscanf(file, "%d/%d", &v, &t);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).tindices[2] = t;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d/%d", &v, &t) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).tindices[2] = t;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else {
+                    /* v */
+                    sscanf(buf, "%d", &v);
+                    T(numtriangles).vindices[0] = v;
+                    fscanf(file, "%d", &v);
+                    T(numtriangles).vindices[1] = v;
+                    fscanf(file, "%d", &v);
+                    T(numtriangles).vindices[2] = v;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d", &v) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                }
+                break;
+                
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+    }
+  }
+  
+#if 0
+  /* announce the memory requirements */
+  printf(" Memory: %d bytes\n",
+      numvertices  * 3*sizeof(GLfloat) +
+      numnormals   * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) +
+      numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) +
+      numtriangles * sizeof(GLMtriangle));
+#endif
+}
+
+
+/* public functions */
+
+
+/* glmUnitize: "unitize" a model by translating it to the origin and
+ * scaling it to fit in a unit cube around the origin.   Returns the
+ * scalefactor used.
+ *
+ * model - properly initialized GLMmodel structure 
+ */
+GLfloat
+glmUnitize(GLMmodel* model)
+{
+    GLuint  i;
+    GLfloat maxx, minx, maxy, miny, maxz, minz;
+    GLfloat cx, cy, cz, w, h, d;
+    GLfloat scale;
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* get the max/mins */
+    maxx = minx = model->vertices[3 + 0];
+    maxy = miny = model->vertices[3 + 1];
+    maxz = minz = model->vertices[3 + 2];
+    for (i = 1; i <= model->numvertices; i++) {
+        if (maxx < model->vertices[3 * i + 0])
+            maxx = model->vertices[3 * i + 0];
+        if (minx > model->vertices[3 * i + 0])
+            minx = model->vertices[3 * i + 0];
+        
+        if (maxy < model->vertices[3 * i + 1])
+            maxy = model->vertices[3 * i + 1];
+        if (miny > model->vertices[3 * i + 1])
+            miny = model->vertices[3 * i + 1];
+        
+        if (maxz < model->vertices[3 * i + 2])
+            maxz = model->vertices[3 * i + 2];
+        if (minz > model->vertices[3 * i + 2])
+            minz = model->vertices[3 * i + 2];
+    }
+    
+    /* calculate model width, height, and depth */
+    w = glmAbs(maxx) + glmAbs(minx);
+    h = glmAbs(maxy) + glmAbs(miny);
+    d = glmAbs(maxz) + glmAbs(minz);
+    
+    /* calculate center of the model */
+    cx = (maxx + minx) / 2.0;
+    cy = (maxy + miny) / 2.0;
+    cz = (maxz + minz) / 2.0;
+    
+    /* calculate unitizing scale factor */
+    scale = 2.0 / glmMax(glmMax(w, h), d);
+    
+    /* translate around center then scale */
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] -= cx;
+        model->vertices[3 * i + 1] -= cy;
+        model->vertices[3 * i + 2] -= cz;
+        model->vertices[3 * i + 0] *= scale;
+        model->vertices[3 * i + 1] *= scale;
+        model->vertices[3 * i + 2] *= scale;
+    }
+    
+    return scale;
+}
+
+/* glmDimensions: Calculates the dimensions (width, height, depth) of
+ * a model.
+ *
+ * model   - initialized GLMmodel structure
+ * dimensions - array of 3 GLfloats (GLfloat dimensions[3])
+ */
+GLvoid
+glmDimensions(GLMmodel* model, GLfloat* dimensions)
+{
+    GLuint i;
+    GLfloat maxx, minx, maxy, miny, maxz, minz;
+    
+    assert(model);
+    assert(model->vertices);
+    assert(dimensions);
+    
+    /* get the max/mins */
+    maxx = minx = model->vertices[3 + 0];
+    maxy = miny = model->vertices[3 + 1];
+    maxz = minz = model->vertices[3 + 2];
+    for (i = 1; i <= model->numvertices; i++) {
+        if (maxx < model->vertices[3 * i + 0])
+            maxx = model->vertices[3 * i + 0];
+        if (minx > model->vertices[3 * i + 0])
+            minx = model->vertices[3 * i + 0];
+        
+        if (maxy < model->vertices[3 * i + 1])
+            maxy = model->vertices[3 * i + 1];
+        if (miny > model->vertices[3 * i + 1])
+            miny = model->vertices[3 * i + 1];
+        
+        if (maxz < model->vertices[3 * i + 2])
+            maxz = model->vertices[3 * i + 2];
+        if (minz > model->vertices[3 * i + 2])
+            minz = model->vertices[3 * i + 2];
+    }
+    
+    /* calculate model width, height, and depth */
+    dimensions[0] = glmAbs(maxx) + glmAbs(minx);
+    dimensions[1] = glmAbs(maxy) + glmAbs(miny);
+    dimensions[2] = glmAbs(maxz) + glmAbs(minz);
+}
+
+/* glmScale: Scales a model by a given amount.
+ * 
+ * model - properly initialized GLMmodel structure
+ * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+ */
+GLvoid
+glmScale(GLMmodel* model, GLfloat scale)
+{
+    GLuint i;
+    
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] *= scale;
+        model->vertices[3 * i + 1] *= scale;
+        model->vertices[3 * i + 2] *= scale;
+    }
+}
+
+/* glmReverseWinding: Reverse the polygon winding for all polygons in
+ * this model.   Default winding is counter-clockwise.  Also changes
+ * the direction of the normals.
+ * 
+ * model - properly initialized GLMmodel structure 
+ */
+GLvoid
+glmReverseWinding(GLMmodel* model)
+{
+    GLuint i, swap;
+    
+    assert(model);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        swap = T(i).vindices[0];
+        T(i).vindices[0] = T(i).vindices[2];
+        T(i).vindices[2] = swap;
+        
+        if (model->numnormals) {
+            swap = T(i).nindices[0];
+            T(i).nindices[0] = T(i).nindices[2];
+            T(i).nindices[2] = swap;
+        }
+        
+        if (model->numtexcoords) {
+            swap = T(i).tindices[0];
+            T(i).tindices[0] = T(i).tindices[2];
+            T(i).tindices[2] = swap;
+        }
+    }
+    
+    /* reverse facet normals */
+    for (i = 1; i <= model->numfacetnorms; i++) {
+        model->facetnorms[3 * i + 0] = -model->facetnorms[3 * i + 0];
+        model->facetnorms[3 * i + 1] = -model->facetnorms[3 * i + 1];
+        model->facetnorms[3 * i + 2] = -model->facetnorms[3 * i + 2];
+    }
+    
+    /* reverse vertex normals */
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = -model->normals[3 * i + 0];
+        model->normals[3 * i + 1] = -model->normals[3 * i + 1];
+        model->normals[3 * i + 2] = -model->normals[3 * i + 2];
+    }
+}
+
+/* glmFacetNormals: Generates facet normals for a model (by taking the
+ * cross product of the two vectors derived from the sides of each
+ * triangle).  Assumes a counter-clockwise winding.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmFacetNormals(GLMmodel* model)
+{
+    GLuint  i;
+    GLfloat u[3];
+    GLfloat v[3];
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* clobber any old facetnormals */
+    if (model->facetnorms)
+        free(model->facetnorms);
+    
+    /* allocate memory for the new facet normals */
+    model->numfacetnorms = model->numtriangles;
+    model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) *
+                       3 * (model->numfacetnorms + 1));
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        model->triangles[i].findex = i+1;
+        
+        u[0] = model->vertices[3 * T(i).vindices[1] + 0] -
+            model->vertices[3 * T(i).vindices[0] + 0];
+        u[1] = model->vertices[3 * T(i).vindices[1] + 1] -
+            model->vertices[3 * T(i).vindices[0] + 1];
+        u[2] = model->vertices[3 * T(i).vindices[1] + 2] -
+            model->vertices[3 * T(i).vindices[0] + 2];
+        
+        v[0] = model->vertices[3 * T(i).vindices[2] + 0] -
+            model->vertices[3 * T(i).vindices[0] + 0];
+        v[1] = model->vertices[3 * T(i).vindices[2] + 1] -
+            model->vertices[3 * T(i).vindices[0] + 1];
+        v[2] = model->vertices[3 * T(i).vindices[2] + 2] -
+            model->vertices[3 * T(i).vindices[0] + 2];
+        
+        glmCross(u, v, &model->facetnorms[3 * (i+1)]);
+        glmNormalize(&model->facetnorms[3 * (i+1)]);
+    }
+}
+
+/* glmVertexNormals: Generates smooth vertex normals for a model.
+ * First builds a list of all the triangles each vertex is in.   Then
+ * loops through each vertex in the the list averaging all the facet
+ * normals of the triangles each vertex is in.   Finally, sets the
+ * normal index in the triangle for the vertex to the generated smooth
+ * normal.   If the dot product of a facet normal and the facet normal
+ * associated with the first triangle in the list of triangles the
+ * current vertex is in is greater than the cosine of the angle
+ * parameter to the function, that facet normal is not added into the
+ * average normal calculation and the corresponding vertex is given
+ * the facet normal.  This tends to preserve hard edges.  The angle to
+ * use depends on the model, but 90 degrees is usually a good start.
+ *
+ * model - initialized GLMmodel structure
+ * angle - maximum angle (in degrees) to smooth across
+ */
+GLvoid
+glmVertexNormals(GLMmodel* model, GLfloat angle)
+{
+    GLMnode*    node;
+    GLMnode*    tail;
+    GLMnode** members;
+    GLfloat*    normals;
+    GLuint  numnormals;
+    GLfloat average[3];
+    GLfloat dot, cos_angle;
+    GLuint  i, avg;
+    
+    assert(model);
+    assert(model->facetnorms);
+    
+    /* calculate the cosine of the angle (in degrees) */
+    cos_angle = cos(angle * M_PI / 180.0);
+    
+    /* nuke any previous normals */
+    if (model->normals)
+        free(model->normals);
+    
+    /* allocate space for new normals */
+    model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
+    
+    /* allocate a structure that will hold a linked list of triangle
+    indices for each vertex */
+    members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1));
+    for (i = 1; i <= model->numvertices; i++)
+        members[i] = NULL;
+    
+    /* for every triangle, create a node for each vertex in it */
+    for (i = 0; i < model->numtriangles; i++) {
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[0]];
+        members[T(i).vindices[0]] = node;
+        
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[1]];
+        members[T(i).vindices[1]] = node;
+        
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[2]];
+        members[T(i).vindices[2]] = node;
+    }
+    
+    /* calculate the average normal for each vertex */
+    numnormals = 1;
+    for (i = 1; i <= model->numvertices; i++) {
+    /* calculate an average normal for this vertex by averaging the
+        facet normal of every triangle this vertex is in */
+        node = members[i];
+        if (!node)
+            fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n");
+        average[0] = 0.0; average[1] = 0.0; average[2] = 0.0;
+        avg = 0;
+        while (node) {
+        /* only average if the dot product of the angle between the two
+        facet normals is greater than the cosine of the threshold
+        angle -- or, said another way, the angle between the two
+            facet normals is less than (or equal to) the threshold angle */
+            dot = glmDot(&model->facetnorms[3 * T(node->index).findex],
+                &model->facetnorms[3 * T(members[i]->index).findex]);
+            if (dot > cos_angle) {
+                node->averaged = GL_TRUE;
+                average[0] += model->facetnorms[3 * T(node->index).findex + 0];
+                average[1] += model->facetnorms[3 * T(node->index).findex + 1];
+                average[2] += model->facetnorms[3 * T(node->index).findex + 2];
+                avg = 1;            /* we averaged at least one normal! */
+            } else {
+                node->averaged = GL_FALSE;
+            }
+            node = node->next;
+        }
+        
+        if (avg) {
+            /* normalize the averaged normal */
+            glmNormalize(average);
+            
+            /* add the normal to the vertex normals list */
+            model->normals[3 * numnormals + 0] = average[0];
+            model->normals[3 * numnormals + 1] = average[1];
+            model->normals[3 * numnormals + 2] = average[2];
+            avg = numnormals;
+            numnormals++;
+        }
+        
+        /* set the normal of this vertex in each triangle it is in */
+        node = members[i];
+        while (node) {
+            if (node->averaged) {
+                /* if this node was averaged, use the average normal */
+                if (T(node->index).vindices[0] == i)
+                    T(node->index).nindices[0] = avg;
+                else if (T(node->index).vindices[1] == i)
+                    T(node->index).nindices[1] = avg;
+                else if (T(node->index).vindices[2] == i)
+                    T(node->index).nindices[2] = avg;
+            } else {
+                /* if this node wasn't averaged, use the facet normal */
+                model->normals[3 * numnormals + 0] = 
+                    model->facetnorms[3 * T(node->index).findex + 0];
+                model->normals[3 * numnormals + 1] = 
+                    model->facetnorms[3 * T(node->index).findex + 1];
+                model->normals[3 * numnormals + 2] = 
+                    model->facetnorms[3 * T(node->index).findex + 2];
+                if (T(node->index).vindices[0] == i)
+                    T(node->index).nindices[0] = numnormals;
+                else if (T(node->index).vindices[1] == i)
+                    T(node->index).nindices[1] = numnormals;
+                else if (T(node->index).vindices[2] == i)
+                    T(node->index).nindices[2] = numnormals;
+                numnormals++;
+            }
+            node = node->next;
+        }
+    }
+    
+    model->numnormals = numnormals - 1;
+    
+    /* free the member information */
+    for (i = 1; i <= model->numvertices; i++) {
+        node = members[i];
+        while (node) {
+            tail = node;
+            node = node->next;
+            free(tail);
+        }
+    }
+    free(members);
+    
+    /* pack the normals array (we previously allocated the maximum
+    number of normals that could possibly be created (numtriangles *
+    3), so get rid of some of them (usually alot unless none of the
+    facet normals were averaged)) */
+    normals = model->normals;
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = normals[3 * i + 0];
+        model->normals[3 * i + 1] = normals[3 * i + 1];
+        model->normals[3 * i + 2] = normals[3 * i + 2];
+    }
+    free(normals);
+}
+
+
+/* glmLinearTexture: Generates texture coordinates according to a
+ * linear projection of the texture map.  It generates these by
+ * linearly mapping the vertices onto a square.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmLinearTexture(GLMmodel* model)
+{
+    GLMgroup *group;
+    GLfloat dimensions[3];
+    GLfloat x, y, scalefactor;
+    GLuint i;
+    
+    assert(model);
+    
+    if (model->texcoords)
+        free(model->texcoords);
+    model->numtexcoords = model->numvertices;
+    model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
+    
+    glmDimensions(model, dimensions);
+    scalefactor = 2.0 / 
+        glmAbs(glmMax(glmMax(dimensions[0], dimensions[1]), dimensions[2]));
+    
+    /* do the calculations */
+    for(i = 1; i <= model->numvertices; i++) {
+        x = model->vertices[3 * i + 0] * scalefactor;
+        y = model->vertices[3 * i + 2] * scalefactor;
+        model->texcoords[2 * i + 0] = (x + 1.0) / 2.0;
+        model->texcoords[2 * i + 1] = (y + 1.0) / 2.0;
+    }
+    
+    /* go through and put texture coordinate indices in all the triangles */
+    group = model->groups;
+    while(group) {
+        for(i = 0; i < group->numtriangles; i++) {
+            T(group->triangles[i]).tindices[0] = T(group->triangles[i]).vindices[0];
+            T(group->triangles[i]).tindices[1] = T(group->triangles[i]).vindices[1];
+            T(group->triangles[i]).tindices[2] = T(group->triangles[i]).vindices[2];
+        }    
+        group = group->next;
+    }
+    
+#if 0
+    printf("glmLinearTexture(): generated %d linear texture coordinates\n",
+        model->numtexcoords);
+#endif
+}
+
+/* glmSpheremapTexture: Generates texture coordinates according to a
+ * spherical projection of the texture map.  Sometimes referred to as
+ * spheremap, or reflection map texture coordinates.  It generates
+ * these by using the normal to calculate where that vertex would map
+ * onto a sphere.  Since it is impossible to map something flat
+ * perfectly onto something spherical, there is distortion at the
+ * poles.  This particular implementation causes the poles along the X
+ * axis to be distorted.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmSpheremapTexture(GLMmodel* model)
+{
+    GLMgroup* group;
+    GLfloat theta, phi, rho, x, y, z, r;
+    GLuint i;
+    
+    assert(model);
+    assert(model->normals);
+    
+    if (model->texcoords)
+        free(model->texcoords);
+    model->numtexcoords = model->numnormals;
+    model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
+    
+    for (i = 1; i <= model->numnormals; i++) {
+        z = model->normals[3 * i + 0];  /* re-arrange for pole distortion */
+        y = model->normals[3 * i + 1];
+        x = model->normals[3 * i + 2];
+        r = sqrt((x * x) + (y * y));
+        rho = sqrt((r * r) + (z * z));
+        
+        if(r == 0.0) {
+            theta = 0.0;
+            phi = 0.0;
+        } else {
+            if(z == 0.0)
+                phi = 3.14159265f / 2.0;
+            else
+                phi = acos(z / rho);
+            
+            if(y == 0.0)
+                theta = 3.141592365f / 2.0;
+            else
+                theta = asin(y / r) + (3.14159265 / 2.0);
+        }
+        
+        model->texcoords[2 * i + 0] = theta / 3.14159265;
+        model->texcoords[2 * i + 1] = phi / 3.14159265;
+    }
+    
+    /* go through and put texcoord indices in all the triangles */
+    group = model->groups;
+    while(group) {
+        for (i = 0; i < group->numtriangles; i++) {
+            T(group->triangles[i]).tindices[0] = T(group->triangles[i]).nindices[0];
+            T(group->triangles[i]).tindices[1] = T(group->triangles[i]).nindices[1];
+            T(group->triangles[i]).tindices[2] = T(group->triangles[i]).nindices[2];
+        }
+        group = group->next;
+    }
+}
+
+/* glmDelete: Deletes a GLMmodel structure.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmDelete(GLMmodel* model)
+{
+    GLMgroup* group;
+    GLuint i;
+    
+    assert(model);
+    
+    if (model->pathname)     free(model->pathname);
+    if (model->mtllibname) free(model->mtllibname);
+    if (model->vertices)     free(model->vertices);
+    if (model->normals)  free(model->normals);
+    if (model->texcoords)  free(model->texcoords);
+    if (model->facetnorms) free(model->facetnorms);
+    if (model->triangles)  free(model->triangles);
+    if (model->materials) {
+        for (i = 0; i < model->nummaterials; i++)
+            free(model->materials[i].name);
+    }
+    free(model->materials);
+    while(model->groups) {
+        group = model->groups;
+        model->groups = model->groups->next;
+        free(group->name);
+        free(group->triangles);
+        free(group);
+    }
+    
+    free(model);
+}
+
+/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+ * Returns a pointer to the created object which should be free'd with
+ * glmDelete().
+ *
+ * filename - name of the file containing the Wavefront .OBJ format data.  
+ */
+GLMmodel* 
+glmReadOBJ(char* filename)
+{
+    GLMmodel* model;
+    FILE*   file;
+    
+    /* open the file */
+    file = fopen(filename, "r");
+    if (!file) {
+        fprintf(stderr, "glmReadOBJ() failed: can't open data file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    
+    /* allocate a new model */
+    model = (GLMmodel*)malloc(sizeof(GLMmodel));
+    model->pathname    = strdup(filename);
+    model->mtllibname    = NULL;
+    model->numvertices   = 0;
+    model->vertices    = NULL;
+    model->numnormals    = 0;
+    model->normals     = NULL;
+    model->numtexcoords  = 0;
+    model->texcoords       = NULL;
+    model->numfacetnorms = 0;
+    model->facetnorms    = NULL;
+    model->numtriangles  = 0;
+    model->triangles       = NULL;
+    model->nummaterials  = 0;
+    model->materials       = NULL;
+    model->numgroups       = 0;
+    model->groups      = NULL;
+    model->position[0]   = 0.0;
+    model->position[1]   = 0.0;
+    model->position[2]   = 0.0;
+    
+    /* make a first pass through the file to get a count of the number
+    of vertices, normals, texcoords & triangles */
+    glmFirstPass(model, file);
+    
+    /* allocate memory */
+    model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
+        3 * (model->numvertices + 1));
+    model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
+        model->numtriangles);
+    if (model->numnormals) {
+        model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
+            3 * (model->numnormals + 1));
+    }
+    if (model->numtexcoords) {
+        model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
+            2 * (model->numtexcoords + 1));
+    }
+    
+    /* rewind to beginning of file and read in the data this pass */
+    rewind(file);
+    
+    glmSecondPass(model, file);
+    
+    /* close the file */
+    fclose(file);
+    
+    return model;
+}
+
+/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+ * a file.
+ *
+ * model - initialized GLMmodel structure
+ * filename - name of the file to write the Wavefront .OBJ format data to
+ * mode  - a bitwise or of values describing what is written to the file
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *             GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLvoid
+glmWriteOBJ(GLMmodel* model, char* filename, GLuint mode)
+{
+    GLuint  i;
+    FILE*   file;
+    GLMgroup* group;
+    
+    assert(model);
+    
+    /* do a bit of warning */
+    if (mode & GLM_FLAT && !model->facetnorms) {
+        printf("glmWriteOBJ() warning: flat normal output requested "
+            "with no facet normals defined.\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_SMOOTH && !model->normals) {
+        printf("glmWriteOBJ() warning: smooth normal output requested "
+            "with no normals defined.\n");
+        mode &= ~GLM_SMOOTH;
+    }
+    if (mode & GLM_TEXTURE && !model->texcoords) {
+        printf("glmWriteOBJ() warning: texture coordinate output requested "
+            "with no texture coordinates defined.\n");
+        mode &= ~GLM_TEXTURE;
+    }
+    if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+        printf("glmWriteOBJ() warning: flat normal output requested "
+            "and smooth normal output requested (using smooth).\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_COLOR && !model->materials) {
+        printf("glmWriteOBJ() warning: color output requested "
+            "with no colors (materials) defined.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_MATERIAL && !model->materials) {
+        printf("glmWriteOBJ() warning: material output requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_MATERIAL;
+    }
+    if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
+        printf("glmWriteOBJ() warning: color and material output requested "
+            "outputting only materials.\n");
+        mode &= ~GLM_COLOR;
+    }
+    
+    
+    /* open the file */
+    file = fopen(filename, "w");
+    if (!file) {
+        fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n",
+            filename);
+        exit(1);
+    }
+    
+    /* spit out a header */
+    fprintf(file, "#  \n");
+    fprintf(file, "#  Wavefront OBJ generated by GLM library\n");
+    fprintf(file, "#  \n");
+    fprintf(file, "#  GLM library\n");
+    fprintf(file, "#  Nate Robins\n");
+    fprintf(file, "#  ndr@pobox.com\n");
+    fprintf(file, "#  http://www.pobox.com/~ndr\n");
+    fprintf(file, "#  \n");
+    
+    if (mode & GLM_MATERIAL && model->mtllibname) {
+        fprintf(file, "\nmtllib %s\n\n", model->mtllibname);
+        glmWriteMTL(model, filename, model->mtllibname);
+    }
+    
+    /* spit out the vertices */
+    fprintf(file, "\n");
+    fprintf(file, "# %d vertices\n", model->numvertices);
+    for (i = 1; i <= model->numvertices; i++) {
+        fprintf(file, "v %f %f %f\n", 
+            model->vertices[3 * i + 0],
+            model->vertices[3 * i + 1],
+            model->vertices[3 * i + 2]);
+    }
+    
+    /* spit out the smooth/flat normals */
+    if (mode & GLM_SMOOTH) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d normals\n", model->numnormals);
+        for (i = 1; i <= model->numnormals; i++) {
+            fprintf(file, "vn %f %f %f\n", 
+                model->normals[3 * i + 0],
+                model->normals[3 * i + 1],
+                model->normals[3 * i + 2]);
+        }
+    } else if (mode & GLM_FLAT) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d normals\n", model->numfacetnorms);
+        for (i = 1; i <= model->numnormals; i++) {
+            fprintf(file, "vn %f %f %f\n", 
+                model->facetnorms[3 * i + 0],
+                model->facetnorms[3 * i + 1],
+                model->facetnorms[3 * i + 2]);
+        }
+    }
+    
+    /* spit out the texture coordinates */
+    if (mode & GLM_TEXTURE) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d texcoords\n", (int)(model->texcoords));
+        for (i = 1; i <= model->numtexcoords; i++) {
+            fprintf(file, "vt %f %f\n", 
+                model->texcoords[2 * i + 0],
+                model->texcoords[2 * i + 1]);
+        }
+    }
+    
+    fprintf(file, "\n");
+    fprintf(file, "# %d groups\n", model->numgroups);
+    fprintf(file, "# %d faces (triangles)\n", model->numtriangles);
+    fprintf(file, "\n");
+    
+    group = model->groups;
+    while(group) {
+        fprintf(file, "g %s\n", group->name);
+        if (mode & GLM_MATERIAL)
+            fprintf(file, "usemtl %s\n", model->materials[group->material].name);
+        for (i = 0; i < group->numtriangles; i++) {
+            if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
+                    T(group->triangles[i]).vindices[0], 
+                    T(group->triangles[i]).nindices[0], 
+                    T(group->triangles[i]).tindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).nindices[1],
+                    T(group->triangles[i]).tindices[1],
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).nindices[2],
+                    T(group->triangles[i]).tindices[2]);
+            } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d %d/%d %d/%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).findex);
+            } else if (mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d %d/%d %d/%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).tindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).tindices[1],
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).tindices[2]);
+            } else if (mode & GLM_SMOOTH) {
+                fprintf(file, "f %d//%d %d//%d %d//%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).nindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).nindices[1],
+                    T(group->triangles[i]).vindices[2], 
+                    T(group->triangles[i]).nindices[2]);
+            } else if (mode & GLM_FLAT) {
+                fprintf(file, "f %d//%d %d//%d %d//%d\n",
+                    T(group->triangles[i]).vindices[0], 
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).findex);
+            } else {
+                fprintf(file, "f %d %d %d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).vindices[2]);
+            }
+        }
+        fprintf(file, "\n");
+        group = group->next;
+    }
+    
+    fclose(file);
+}
+
+/* glmDraw: Renders the model to the current OpenGL context using the
+ * mode specified.
+ *
+ * model - initialized GLMmodel structure
+ * mode  - a bitwise OR of values describing what is to be rendered.
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *             GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLvoid
+glmDraw(GLMmodel* model, GLuint mode)
+{
+    static GLuint i;
+    static GLMgroup* group;
+    static GLMtriangle* triangle;
+    static GLMmaterial* material;
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* do a bit of warning */
+    if (mode & GLM_FLAT && !model->facetnorms) {
+        printf("glmDraw() warning: flat render mode requested "
+            "with no facet normals defined.\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_SMOOTH && !model->normals) {
+        printf("glmDraw() warning: smooth render mode requested "
+            "with no normals defined.\n");
+        mode &= ~GLM_SMOOTH;
+    }
+    if (mode & GLM_TEXTURE && !model->texcoords) {
+        printf("glmDraw() warning: texture render mode requested "
+            "with no texture coordinates defined.\n");
+        mode &= ~GLM_TEXTURE;
+    }
+    if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+        printf("glmDraw() warning: flat render mode requested "
+            "and smooth render mode requested (using smooth).\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_COLOR && !model->materials) {
+        printf("glmDraw() warning: color render mode requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_MATERIAL && !model->materials) {
+        printf("glmDraw() warning: material render mode requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_MATERIAL;
+    }
+    if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
+        printf("glmDraw() warning: color and material render mode requested "
+            "using only material mode.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_COLOR)
+        glEnable(GL_COLOR_MATERIAL);
+    else if (mode & GLM_MATERIAL)
+        glDisable(GL_COLOR_MATERIAL);
+    
+    /* perhaps this loop should be unrolled into material, color, flat,
+       smooth, etc. loops?  since most cpu's have good branch prediction
+       schemes (and these branches will always go one way), probably
+       wouldn't gain too much?  */
+    
+    group = model->groups;
+    while (group) {
+        if (mode & GLM_MATERIAL) {
+            material = &model->materials[group->material];
+            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient);
+            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse);
+            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material->specular);
+            glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess);
+        }
+        
+        if (mode & GLM_COLOR) {
+            glColor3fv(material->diffuse);
+        }
+        
+        glBegin(GL_TRIANGLES);
+        for (i = 0; i < group->numtriangles; i++) {
+            triangle = &T(group->triangles[i]);
+            
+            if (mode & GLM_FLAT)
+                glNormal3fv(&model->facetnorms[3 * triangle->findex]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[0]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[0]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[0]]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[1]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[1]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[1]]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[2]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[2]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[2]]);
+            
+        }
+        glEnd();
+        
+        group = group->next;
+    }
+}
+
+/* glmList: Generates and returns a display list for the model using
+ * the mode specified.
+ *
+ * model - initialized GLMmodel structure
+ * mode  - a bitwise OR of values describing what is to be rendered.
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ * GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLuint
+glmList(GLMmodel* model, GLuint mode)
+{
+    GLuint list;
+    
+    list = glGenLists(1);
+    glNewList(list, GL_COMPILE);
+    glmDraw(model, mode);
+    glEndList();
+    
+    return list;
+}
+
+/* glmWeld: eliminate (weld) vectors that are within an epsilon of
+ * each other.
+ *
+ * model   - initialized GLMmodel structure
+ * epsilon     - maximum difference between vertices
+ *               ( 0.00001 is a good start for a unitized model)
+ *
+ */
+GLvoid
+glmWeld(GLMmodel* model, GLfloat epsilon)
+{
+    GLfloat* vectors;
+    GLfloat* copies;
+    GLuint   numvectors;
+    GLuint   i;
+    
+    /* vertices */
+    numvectors = model->numvertices;
+    vectors  = model->vertices;
+    copies = glmWeldVectors(vectors, &numvectors, epsilon);
+    
+#if 1
+    printf("glmWeld(): %d redundant vertices.\n", 
+        model->numvertices - numvectors - 1);
+#endif
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        T(i).vindices[0] = (GLuint)vectors[3 * T(i).vindices[0] + 0];
+        T(i).vindices[1] = (GLuint)vectors[3 * T(i).vindices[1] + 0];
+        T(i).vindices[2] = (GLuint)vectors[3 * T(i).vindices[2] + 0];
+    }
+    
+    /* free space for old vertices */
+    free(vectors);
+    
+    /* allocate space for the new vertices */
+    model->numvertices = numvectors;
+    model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * 
+        3 * (model->numvertices + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] = copies[3 * i + 0];
+        model->vertices[3 * i + 1] = copies[3 * i + 1];
+        model->vertices[3 * i + 2] = copies[3 * i + 2];
+    }
+    
+    free(copies);
+}
+
+/* glmReadPPM: read a PPM raw (type P6) file.  The PPM file has a header
+ * that should look something like:
+ *
+ *    P6
+ *    # comment
+ *    width height max_value
+ *    rgbrgbrgb...
+ *
+ * where "P6" is the magic cookie which identifies the file type and
+ * should be the only characters on the first line followed by a
+ * carriage return.  Any line starting with a # mark will be treated
+ * as a comment and discarded.   After the magic cookie, three integer
+ * values are expected: width, height of the image and the maximum
+ * value for a pixel (max_value must be < 256 for PPM raw files).  The
+ * data section consists of width*height rgb triplets (one byte each)
+ * in binary format (i.e., such as that written with fwrite() or
+ * equivalent).
+ *
+ * The rgb data is returned as an array of unsigned chars (packed
+ * rgb).  The malloc()'d memory should be free()'d by the caller.  If
+ * an error occurs, an error message is sent to stderr and NULL is
+ * returned.
+ *
+ * filename   - name of the .ppm file.
+ * width      - will contain the width of the image on return.
+ * height     - will contain the height of the image on return.
+ *
+ */
+GLubyte* 
+glmReadPPM(char* filename, int* width, int* height)
+{
+    FILE* fp;
+    int i, w, h, d;
+    unsigned char* image;
+    char head[70];          /* max line <= 70 in PPM (per spec). */
+    
+    fp = fopen(filename, "rb");
+    if (!fp) {
+        perror(filename);
+        return NULL;
+    }
+    
+    /* grab first two chars of the file and make sure that it has the
+       correct magic cookie for a raw PPM file. */
+    fgets(head, 70, fp);
+    if (strncmp(head, "P6", 2)) {
+        fprintf(stderr, "%s: Not a raw PPM file\n", filename);
+        return NULL;
+    }
+    
+    /* grab the three elements in the header (height, width, maxval). */
+    i = 0;
+    while(i < 3) {
+        fgets(head, 70, fp);
+        if (head[0] == '#')     /* skip comments. */
+            continue;
+        if (i == 0)
+            i += sscanf(head, "%d %d %d", &h, &w, &d);
+        else if (i == 1)
+            i += sscanf(head, "%d %d", &w, &d);
+        else if (i == 2)
+            i += sscanf(head, "%d", &d);
+    }
+    
+    /* grab all the image data in one fell swoop. */
+    image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
+    fread(image, sizeof(unsigned char), w*h*3, fp);
+    fclose(fp);
+    
+    *width = w;
+    *height = h;
+    return image;
+}
+
+#if 0
+/* normals */
+if (model->numnormals) {
+    numvectors = model->numnormals;
+    vectors  = model->normals;
+    copies = glmOptimizeVectors(vectors, &numvectors);
+    
+    printf("glmOptimize(): %d redundant normals.\n", 
+        model->numnormals - numvectors);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        T(i).nindices[0] = (GLuint)vectors[3 * T(i).nindices[0] + 0];
+        T(i).nindices[1] = (GLuint)vectors[3 * T(i).nindices[1] + 0];
+        T(i).nindices[2] = (GLuint)vectors[3 * T(i).nindices[2] + 0];
+    }
+    
+    /* free space for old normals */
+    free(vectors);
+    
+    /* allocate space for the new normals */
+    model->numnormals = numvectors;
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat) * 
+        3 * (model->numnormals + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = copies[3 * i + 0];
+        model->normals[3 * i + 1] = copies[3 * i + 1];
+        model->normals[3 * i + 2] = copies[3 * i + 2];
+    }
+    
+    free(copies);
+}
+
+/* texcoords */
+if (model->numtexcoords) {
+    numvectors = model->numtexcoords;
+    vectors  = model->texcoords;
+    copies = glmOptimizeVectors(vectors, &numvectors);
+    
+    printf("glmOptimize(): %d redundant texcoords.\n", 
+        model->numtexcoords - numvectors);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        for (j = 0; j < 3; j++) {
+            T(i).tindices[j] = (GLuint)vectors[3 * T(i).tindices[j] + 0];
+        }
+    }
+    
+    /* free space for old texcoords */
+    free(vectors);
+    
+    /* allocate space for the new texcoords */
+    model->numtexcoords = numvectors;
+    model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 
+        2 * (model->numtexcoords + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numtexcoords; i++) {
+        model->texcoords[2 * i + 0] = copies[2 * i + 0];
+        model->texcoords[2 * i + 1] = copies[2 * i + 1];
+    }
+    
+    free(copies);
+}
+#endif
+
+#if 0
+/* look for unused vertices */
+/* look for unused normals */
+/* look for unused texcoords */
+for (i = 1; i <= model->numvertices; i++) {
+    for (j = 0; j < model->numtriangles; i++) {
+        if (T(j).vindices[0] == i || 
+            T(j).vindices[1] == i || 
+            T(j).vindices[1] == i)
+            break;
+    }
+}
+#endif
Index: projectionDesigner/trunk/projdesigner/src/gui/Defines.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/Defines.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/Defines.cpp	(revision 4)
@@ -0,0 +1,13 @@
+#include "gui/Defines.h"
+
+using namespace projection;
+
+QString projection::formatValue(double value)
+{
+    return QString::number(value, 'f', 4);
+}
+
+double projection::formatValue(const QString& value)
+{
+    return value.toDouble();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QChannelManagerWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QChannelManagerWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QChannelManagerWidget.cpp	(revision 4)
@@ -0,0 +1,170 @@
+#include "ProjectionModel.h"
+#include "Channel.h"
+#include "gui/QChannelWidget.h"
+#include "gui/QProjectorWindow.h"
+
+#include "gui/QChannelManagerWidget.h"
+
+using namespace projection;
+
+QChannelManagerWidget::QChannelManagerWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+    connect(ui.channelTable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(channelTableHeaderClicked(int)));
+}
+
+QChannelManagerWidget::~QChannelManagerWidget()
+{
+}
+
+void QChannelManagerWidget::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+
+    updateGUI();
+}
+
+void QChannelManagerWidget::selectChannel(int index)
+{
+    if (index < ui.channelTable->rowCount()) {
+        ui.channelTable->selectRow(index);
+    }
+}
+
+int QChannelManagerWidget::getSelectedChannel() const
+{
+    return ui.channelTable->currentRow();
+}
+
+void QChannelManagerWidget::updateChannelNamesGUI()
+{
+    for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+        ui.channelTable->item(i, 0)->setText(m_pModel->getChannel(i)->getName());
+}
+
+void QChannelManagerWidget::addChannelToTable(int row, Channel* pChannel)
+{
+    ui.channelTable->setItem(row, 0, new QTableWidgetItem(pChannel->getName()));
+    QCheckBox* pCheckBox;
+    pCheckBox = new QCheckBox(ui.channelTable); pCheckBox->setTristate(true);
+    if (pChannel->getProjector()->getShow()) pCheckBox->setChecked(true);
+    if (pChannel->getProjector()->getShowArea()) pCheckBox->setCheckState(Qt::PartiallyChecked);
+    connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(channelStateChanged()));
+    if (pChannel->getProjector()->getShow()) pCheckBox->setChecked(true);
+    ui.channelTable->setCellWidget(row, 1, pCheckBox);
+    pCheckBox = new QCheckBox(ui.channelTable); pCheckBox->setTristate(true);
+    if (pChannel->getView()->getShow()) pCheckBox->setChecked(true);
+    if (pChannel->getView()->getShowArea()) pCheckBox->setCheckState(Qt::PartiallyChecked);
+    connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(channelStateChanged()));
+    if (pChannel->getView()->getShow()) pCheckBox->setChecked(true);
+    ui.channelTable->setCellWidget(row, 2, pCheckBox);
+    pCheckBox = new QCheckBox(ui.channelTable);
+    if (pChannel->getShowProjectedScene()) pCheckBox->setChecked(true);
+    connect(pCheckBox, SIGNAL(stateChanged(int)), this, SLOT(channelStateChanged()));
+    ui.channelTable->setCellWidget(row, 3, pCheckBox);
+}
+
+void QChannelManagerWidget::updateGUI()
+{
+    if (m_pModel)
+    {
+        unsigned int currentRow = ui.channelTable->currentRow();
+        ui.channelTable->clear();
+        ui.channelTable->setColumnCount(4);
+        QStringList labels;
+        labels << "        Name        " << "P" << "V" << "S";  // Name's Streach flag is ignored in Qt 4.1
+        ui.channelTable->setHorizontalHeaderLabels(labels);
+        ui.channelTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
+        ui.channelTable->setShowGrid(false);
+        for (int j=1; j<4; ++j) {
+            ui.channelTable->horizontalHeader()->setResizeMode(j, QHeaderView::Custom);
+        }
+        ui.channelTable->resizeColumnsToContents();
+        ui.channelTable->setRowCount(m_pModel->getNumChannels());
+        for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+            addChannelToTable(i, m_pModel->getChannel(i));
+        ui.channelTable->resizeRowsToContents();
+        ui.channelTable->setCurrentCell(currentRow, 0);
+    }
+}
+
+void QChannelManagerWidget::on_addButton_clicked()
+{
+    Channel* pChannel = m_pModel->addChannel();
+    ui.channelTable->insertRow(ui.channelTable->rowCount());
+    addChannelToTable(ui.channelTable->rowCount()-1, pChannel);
+    ui.channelTable->resizeRowsToContents();
+    ui.channelTable->setCurrentCell(ui.channelTable->rowCount()-1, 0);
+}
+
+void QChannelManagerWidget::on_removeButton_clicked()
+{
+    unsigned int currentRow = ui.channelTable->currentRow();
+    ui.channelTable->removeRow(currentRow);
+    m_pModel->removeChannel(currentRow);
+}
+
+void QChannelManagerWidget::on_channelTable_currentCellChanged(int currentRow, int , int , int )
+{
+    m_pModel->selectChannel(m_pModel->getChannel(currentRow));
+}
+
+void QChannelManagerWidget::on_channelTable_itemChanged(QTableWidgetItem* pItem)
+{
+    if (ui.channelTable->column(pItem) == 0)
+    {
+        Channel* pChannel = m_pModel->getChannel(ui.channelTable->row(pItem));
+        if (pChannel->getName() != pItem->text())
+            pChannel->setName(pItem->text());
+    }
+}
+
+void QChannelManagerWidget::channelTableHeaderClicked(int index)
+{
+    if (ui.channelTable->rowCount() == 0 || index == 0 || index > 3)
+        return;
+    int currentRow = ui.channelTable->currentRow();
+    if (currentRow < 0)
+        currentRow = 0;
+    Qt::CheckState checkState=Qt::Unchecked;
+    if (index == 1 || index == 2)
+    {
+        switch (((QCheckBox*)ui.channelTable->cellWidget(currentRow, index))->checkState()) {
+            case Qt::Unchecked: checkState = Qt::PartiallyChecked; break;
+            case Qt::PartiallyChecked: checkState = Qt::Checked; break;
+            case Qt::Checked: checkState = Qt::Unchecked; break;
+        }
+    }
+    else if (index == 3)
+    {
+        switch (((QCheckBox*)ui.channelTable->cellWidget(currentRow, 3))->checkState()) {
+            case Qt::Unchecked: checkState = Qt::Checked; break;
+            case Qt::Checked: checkState = Qt::Unchecked; break;
+            case Qt::PartiallyChecked: checkState = Qt::Unchecked; break;
+        }
+    }
+    m_pModel->setBlockUpdate(true);
+    for (int i=0; i<ui.channelTable->rowCount(); ++i)
+        ((QCheckBox*)ui.channelTable->cellWidget(i, index))->setCheckState(checkState);
+    m_pModel->setBlockUpdate(false);
+    m_pModel->updateViews();
+}
+
+void QChannelManagerWidget::channelStateChanged()
+{
+    int currentRow = -1;
+    for (int i=0; i<ui.channelTable->rowCount(); ++i)
+        for (int j=1; j<4; ++j)
+            if (ui.channelTable->cellWidget(i, j) == sender()) {
+                currentRow = i;
+                break;
+            }
+    if (currentRow < 0) return;
+    Channel* pChannel = m_pModel->getChannel(currentRow);
+    pChannel->getProjector()->setShow(((QCheckBox*)ui.channelTable->cellWidget(currentRow, 1))->checkState()==Qt::Checked);
+    pChannel->getProjector()->setShowArea(((QCheckBox*)ui.channelTable->cellWidget(currentRow, 1))->checkState()!=Qt::Unchecked);
+    pChannel->getView()->setShow(((QCheckBox*)ui.channelTable->cellWidget(currentRow, 2))->checkState()==Qt::Checked);
+    pChannel->getView()->setShowArea(((QCheckBox*)ui.channelTable->cellWidget(currentRow, 2))->checkState()!=Qt::Unchecked);
+    pChannel->setShowProjectedScene(((QCheckBox*)ui.channelTable->cellWidget(currentRow, 3))->checkState()!=Qt::Unchecked);
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QChannelWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QChannelWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QChannelWidget.cpp	(revision 4)
@@ -0,0 +1,294 @@
+#include "ProjectionModel.h"
+#include "Channel.h"
+#include "Warp.h"
+#include "gui/QChannelWidget.h"
+#include "gui/QDesignViewWindow.h"
+
+using namespace projection;
+
+QChannelWidget::QChannelWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags), m_pChannel(NULL)
+{
+    ui.setupUi(this);
+
+    ui.pluginComboBox->clear();
+
+ 		foreach (ProjectorInterface *projector_interface, ProjectionModel::projector_interfaces)
+				{
+						foreach (QString projector_name, projector_interface->projectors())
+								{
+										ProjectorWidget* projector_widget = projector_interface->newProjectorWidget(projector_name);
+										Q_ASSERT (NULL!=projector_widget);
+										ui.stackedWidget->addWidget(projector_widget);
+										ui.pluginComboBox->addItem(projector_widget->data().getFullName());
+								}
+				}
+
+		// If we only have the default plugin, the combo is not displayed.
+		if (ui.pluginComboBox->count()==1) 
+		{
+				ui.pluginComboBox->hide();
+				ui.pluginLabel->hide();
+		}
+		
+
+		connect(ui.pluginComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(on_pluginComboBox_currentIndexChanged(int)));
+
+    ui.toolBox->setAutoFillBackground(false);
+
+    setEnabled(false);
+
+		ui.projectionTransformWidget->disconnect();
+		connect(ui.projectionTransformWidget, SIGNAL(matrixChanged(const TransformMatrix&)),
+						this, SLOT(on_projectionTransformWidget_matrixChanged(const TransformMatrix&)));
+
+		ui.projectionTransformWidget->setUseScale(false);
+		ui.viewTransformWidget->setUseScale(false);
+}
+
+QChannelWidget::~QChannelWidget()
+{
+}
+
+void QChannelWidget::setChannel(Channel* pChannel)
+{
+		if (m_pChannel==pChannel) return;
+
+    m_pChannel = pChannel;
+
+		if (pChannel) 
+		{
+				Q_ASSERT(NULL!=pChannel->getProjector());
+				QString fullname=pChannel->getProjector()->getFullName();
+				int next_index=ui.pluginComboBox->findText(fullname);
+				ui.pluginComboBox->setCurrentIndex(next_index);
+
+				// In some case, the on_pluginComboBox_currentIndexChanged is not called at first time (because the index does not change indeed).
+				// So, we force the connection
+				ProjectorWidget* projector_widget=qobject_cast<ProjectorWidget*>(ui.stackedWidget->currentWidget());
+				projector_widget->disconnect();
+				m_pChannel->disconnect();
+
+				connect(projector_widget, SIGNAL(dataChanged(const ProjectorData&)), m_pChannel, SLOT(updatePluginData(const ProjectorData&)));
+				
+		}
+		else ui.pluginComboBox->setCurrentIndex(0);
+		updateGUI();
+
+		setEnabled(NULL!=pChannel);
+}
+
+Channel* QChannelWidget::getChannel() const
+{
+    return m_pChannel;
+}
+
+void QChannelWidget::updateGUI()
+{
+    if (m_pChannel)
+    {
+        ui.nameEdit->setText(m_pChannel->getName());
+        ui.overlayNameCheckBox->setChecked(m_pChannel->getOverlayName());
+        ui.remoteHostNameEdit->setText(m_pChannel->getRemoteHostName());
+        ui.remoteFullScreenCheckBox->setChecked(m_pChannel->getRemoteFullScreen());
+        ui.remoteScreenComboBox->setCurrentIndex(ui.remoteScreenComboBox->findText(QString::number(m_pChannel->getRemoteScreen())));
+        ui.overlayImageEdit->setText(m_pChannel->getOverlayImageFileName());
+
+				// On s'occupe de la partie Projection
+				// Inutile si elle n'est pas selectionnee, d'ailleurs.
+
+				// On met a jour les donnees.
+				const ProjectorData* projector_data=m_pChannel->getProjector();
+				ProjectorWidget* projector_widget=qobject_cast<ProjectorWidget*>(ui.stackedWidget->currentWidget());
+				projector_widget->updateGUI(projector_data);
+
+				ui.projectionTransformWidget->setMatrix(m_pChannel->getProjectorTransformMatrix());
+
+        ui.warpCheckBox->setChecked(m_pChannel->getDistWarpEnabled());
+        ui.warpResSpinBox->setValue(m_pChannel->getDistWarp()->getNumCtrlPoints());
+
+
+
+
+				// On s'occupe de la partie View
+				// Inutile si elle n'est pas selectionnee, d'ailleurs.
+
+
+				ui.viewProjectionWidget->disconnect();
+				ui.viewTransformWidget->disconnect();
+
+				connect(ui.viewProjectionWidget, SIGNAL(matrixChanged(const ProjectionMatrix&)),
+								this, SLOT(on_viewProjectionWidget_matrixChanged(const ProjectionMatrix&)));
+				connect(ui.viewTransformWidget, SIGNAL(matrixChanged(const TransformMatrix&)),
+								this, SLOT(on_viewTransformWidget_matrixChanged(const TransformMatrix&)));
+				ui.viewProjectionWidget->setMatrix(m_pChannel->getView()->getProjectionMatrix());
+				ui.viewTransformWidget->setMatrix(m_pChannel->getView()->getTransformMatrix());
+
+    }
+    else
+    {
+        ui.nameEdit->setText("");
+        ui.overlayNameCheckBox->setChecked(false);
+        ui.remoteHostNameEdit->setText("");
+        ui.remoteFullScreenCheckBox->setChecked(false);
+        ui.remoteScreenComboBox->setCurrentIndex(0);
+        ui.overlayImageEdit->setText("");
+
+				ui.projectionTransformWidget->clear();
+				ui.viewProjectionWidget->clear();
+				ui.viewTransformWidget->clear();
+
+				Q_ASSERT(NULL!=ui.stackedWidget);
+				if (NULL!=ui.stackedWidget->currentWidget())
+				{
+						ProjectorWidget* projector_widget=qobject_cast<ProjectorWidget*>(ui.stackedWidget->currentWidget());
+						Q_ASSERT(NULL!=projector_widget);
+						projector_widget->clear();
+						
+				}
+		}
+}
+
+void QChannelWidget::on_nameEdit_editingFinished()
+{
+    if (m_pChannel)
+    {
+        if (m_pChannel->getName() != ui.nameEdit->text())
+        {
+            m_pChannel->setName(ui.nameEdit->text());
+            ui.nameEdit->setText(m_pChannel->getName());
+        }
+    }
+}
+
+void QChannelWidget::on_overlayNameCheckBox_toggled(bool checked)
+{
+    if (m_pChannel)
+    {
+        m_pChannel->setOverlayName(checked);
+    }
+}
+
+void QChannelWidget::on_remoteHostNameEdit_editingFinished()
+{
+    if (m_pChannel)
+    {
+        if (m_pChannel->getRemoteHostName() != ui.remoteHostNameEdit->text())
+            m_pChannel->setRemoteHostName(ui.remoteHostNameEdit->text());
+    }
+}
+
+void QChannelWidget::on_remoteFullScreenCheckBox_toggled(bool checked)
+{
+    if (m_pChannel)
+    {
+        m_pChannel->setRemoteFullScreen(checked);
+    }
+}
+
+void QChannelWidget::on_remoteScreenComboBox_activated(int)
+{
+    if (m_pChannel)
+    {
+        m_pChannel->setRemoteScreen(ui.remoteScreenComboBox->currentText().toInt());
+    }
+}
+
+void QChannelWidget::on_overlayImageEdit_editingFinished()
+{
+    if (m_pChannel)
+    {
+        if (m_pChannel->getOverlayImageFileName() != ui.overlayImageEdit->text())
+            m_pChannel->setOverlayImageFileName(ui.overlayImageEdit->text());
+    }
+}
+
+void QChannelWidget::on_overlayImageBrowseButton_clicked()
+{
+    if (m_pChannel)
+    {
+        QString fileName = QFileDialog::getOpenFileName(this, "Choose a file to open", ui.overlayImageEdit->text(), "Image files (*.*)");
+        if (!fileName.isEmpty()) {
+            ui.overlayImageEdit->setText(fileName);
+            on_overlayImageEdit_editingFinished();
+        }
+    }
+}
+
+void QChannelWidget::on_warpCheckBox_toggled(bool checked)
+{
+    if (m_pChannel)
+    {
+        m_pChannel->setDistWarpEnabled(checked);
+    }
+}
+
+void QChannelWidget::on_warpResSpinBox_valueChanged(int value)
+{
+    if (m_pChannel)
+    {
+        m_pChannel->getDistWarp()->setNumCtrlPoints(value);
+        m_pChannel->updateData();
+    }
+}
+
+void QChannelWidget::on_warpResetButton_clicked()
+{
+    if (m_pChannel)
+    {
+        m_pChannel->getDistWarp()->reset();
+        m_pChannel->updateData();
+    }
+}
+
+void QChannelWidget::on_calibrateButton_clicked()
+{
+}
+
+void QChannelWidget::on_fitButton_clicked()
+{
+    if (m_pChannel)
+    {
+        m_pChannel->fitView();
+    }
+}
+
+void QChannelWidget::on_windowButton_clicked()
+{
+    if (m_pChannel)
+    {
+        m_pChannel->showProjectorWindow();
+    }
+}
+
+void QChannelWidget::on_projectionTransformWidget_matrixChanged(const TransformMatrix& matrix)
+{
+		m_pChannel->setProjectorTransformMatrix(matrix);
+}
+
+void QChannelWidget::on_viewProjectionWidget_matrixChanged(const ProjectionMatrix& matrix)
+{
+		m_pChannel->setViewProjectionMatrix(matrix);
+}
+
+void QChannelWidget::on_viewTransformWidget_matrixChanged(const TransformMatrix& matrix)
+{
+		m_pChannel->setViewTransformMatrix(matrix);
+}
+
+void QChannelWidget::on_pluginComboBox_currentIndexChanged(int current_index)
+{
+		ui.stackedWidget->currentWidget()->disconnect();
+		ui.stackedWidget->setCurrentIndex(current_index);
+		ui.stackedWidget->currentWidget()->disconnect();
+		if (m_pChannel)
+		{
+				m_pChannel->setProjector (ui.pluginComboBox->currentText());
+				ProjectorWidget* projector_widget=qobject_cast<ProjectorWidget*>(ui.stackedWidget->currentWidget());
+				m_pChannel->disconnect();
+				connect(projector_widget, SIGNAL(dataChanged(const ProjectorData&)), m_pChannel, SLOT(updatePluginData(const ProjectorData&)));
+				m_pChannel->updateData();
+				
+		}
+		updateGUI();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QClientWindow.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QClientWindow.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QClientWindow.cpp	(revision 4)
@@ -0,0 +1,26 @@
+#include <QApplication>
+#include "gui/QClientWindow.h"
+
+using namespace projection;
+
+QClientWindow::QClientWindow(QWidget* pParent, Qt::WFlags flags)
+    : QMainWindow(pParent, flags)
+{
+    ui.setupUi(this);
+
+    statusBar();
+}
+
+QClientWindow::~QClientWindow()
+{
+}
+
+void QClientWindow::appendLog(const QString& line)
+{
+    ui.logEdit->append(line.trimmed());
+}
+
+void QClientWindow::on_actionFileExit_triggered()
+{
+    qApp->closeAllWindows();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QConnectionDialog.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QConnectionDialog.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QConnectionDialog.cpp	(revision 4)
@@ -0,0 +1,54 @@
+#include "gui/QConnectionDialog.h"
+
+using namespace distortion;
+
+QConnectionDialog::QConnectionDialog(QWidget* pParent, Qt::WFlags flags)
+    : QDialog(pParent, flags)
+{
+    ui.setupUi(this);
+}
+
+QConnectionDialog::~QConnectionDialog()
+{
+    exit(0);
+}
+
+void QConnectionDialog::on_closeButton_clicked()
+{
+    exit(0);
+}
+
+void QConnectionDialog::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        int posX = 16;
+        int posY = 16;
+        int width = 0;
+        int height = 0;
+
+        QDomElement geom = element.firstChildElement("Geometry");
+        posX = geom.attribute("posX").toInt();
+        posY = geom.attribute("posY").toInt();
+        width = geom.attribute("width").toInt();
+        height = geom.attribute("height").toInt();
+
+        move(posX, posY);
+        if (width!=0 && height!=0)
+            resize(width, height);
+    }
+}
+
+QDomElement QConnectionDialog::domElement(QDomDocument& document) const
+{
+    QDomElement de = document.createElement("ConnectionDialog");
+
+    QDomElement geom = document.createElement("Geometry");
+    geom.setAttribute("posX", pos().x());
+    geom.setAttribute("posY", pos().y());
+    geom.setAttribute("width", width());
+    geom.setAttribute("height", height());
+    de.appendChild(geom);
+
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWidget.cpp	(revision 4)
@@ -0,0 +1,486 @@
+#include "ProjectionModel.h"
+#include <QMessageBox>
+#include <QGLPixelBuffer>
+
+#include "Scene.h"
+#include "Screen.h"
+#include "Channel.h"
+#pragma warning(disable: 4003)
+#include "gmtl/gmtl.h"
+#include "gui/QDesignViewWidget.h"
+
+using namespace projection;
+using namespace gmtl;
+
+QDesignViewWidget::QDesignViewWidget(QWidget* pParent, const QGLWidget* pSharedWidget, Qt::WFlags flags)
+    : QGLViewerWidget(pParent, pSharedWidget, flags)
+{
+    m_pModel = NULL;
+
+    m_viewMode = DESIGN_VIEWMODE_PERSPECTIVE;
+    m_opMode = DESIGN_OPMODE_PROJECTOR;
+    m_transMode = DESIGN_TRANSMODE_LOCAL;
+
+    m_bAxisVisible = true;
+    m_bGridVisible = true;
+    m_bInfoVisible = true;
+
+    m_gridSize = 2.0f;
+
+    m_infoFont.setFamily("Helvetica");
+    m_infoFont.setPointSize(14);
+
+    if (!QGLPixelBuffer::hasOpenGLPbuffers())
+        QMessageBox::critical(this, APPLICATION_NAME,
+                              tr("%1 requires OpenGL P-Buffer feature.").arg(APPLICATION_NAME));
+}
+
+void QDesignViewWidget::init()
+{
+}
+
+QDesignViewWidget::~QDesignViewWidget()
+{
+}
+
+void QDesignViewWidget::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+
+    setSceneSize(m_pModel->getScreen()->getSize() * 5.0f);
+    setView(Vec3f(),
+            makeRot<Quatf>(AxisAnglef(Math::deg2Rad(45.0f), Vec3f(0.0f, 1.0f, 0.0f))) *
+            makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-30.0f), Vec3f(1.0f, 0.0f, 0.0f))),
+            sceneSize()*0.5f);
+}
+
+void QDesignViewWidget::draw()
+{
+    if (!isVisible()) return;
+
+    m_pModel->setRenderContext(this);
+
+    m_sceneSize = m_pModel->getScreen()->getSize() * 5.0f;
+
+    glViewport(0, 0, width(), height());
+
+    glEnable(GL_COLOR_MATERIAL);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    if (m_pModel->getScene()->getShowInDesignView())
+    {
+        glPushMatrix();
+        glMultMatrixf(invert(m_pModel->getScene()->getCameraMatrix()).getData());
+        m_pModel->getScene()->draw();
+        glPopMatrix();
+    }
+
+    glPushMatrix();
+    m_pModel->getScreen()->draw();
+    m_pModel->getScreen()->drawFrame();
+    for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+    {
+        if (m_pModel->getChannel(i)->getProjector()->getShowArea())
+            m_pModel->getScreen()->draw(PROJECT_SOURCE_PROJECTORAREA, m_pModel->getChannel(i));
+        if (m_pModel->getChannel(i)->getView()->getShowArea())
+            m_pModel->getScreen()->draw(PROJECT_SOURCE_VIEWAREA, m_pModel->getChannel(i));
+        if (m_pModel->getChannel(i)->getShowProjectedScene())
+            m_pModel->getScreen()->draw(PROJECT_SOURCE_SCENE, m_pModel->getChannel(i));
+        makeCurrent();
+    }
+    glPopMatrix();
+
+    for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+    {
+        glPushMatrix();
+        m_pModel->getChannel(i)->drawFrustums(m_pModel->getChannel(i)==m_pModel->getSelectedChannel());
+        glPopMatrix();
+    }
+
+    glPushAttrib(GL_ENABLE_BIT);
+    glDisable(GL_LIGHTING);
+    for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
+    {
+        if (m_pModel->getChannel(i)->getProjector()->getShow())
+        {
+            glPushMatrix();
+            glMultMatrixf(m_pModel->getChannel(i)->getProjectorTransformMatrix().getMatrix().getData());
+            glTranslatef(0.0f, 0.0f, 0.05f);
+            renderText(0, 0, 0, m_pModel->getChannel(i)->getName(), m_infoFont, 5000);
+            glPopMatrix();
+        }
+        if (m_pModel->getChannel(i)->getView()->getShow())
+        {
+            glPushMatrix();
+            glMultMatrixf(m_pModel->getChannel(i)->getView()->getTransformMatrix().getMatrix().getData());
+            glTranslatef(0.0f, 0.0f, 0.05f);
+            renderText(0, 0, 0, m_pModel->getChannel(i)->getName(), m_infoFont, 5000);
+            glPopMatrix();
+        }
+    }
+    glPopAttrib();
+
+    if (m_bInfoVisible)
+    {
+        glDisable(GL_LIGHTING);
+
+        int x = int(m_infoFont.pointSize() * 0.5);
+        int y = int(m_infoFont.pointSize() * 1.5);
+        int yoffset = int(m_infoFont.pointSize() * 1.5);
+        switch (m_viewMode)
+        {
+        case DESIGN_VIEWMODE_PERSPECTIVE:
+            renderText(x, y, QString("View Mode: Perspective"), m_infoFont); y += yoffset; break;
+        case DESIGN_VIEWMODE_CENTER:
+            renderText(x, y, QString("View Mode: Center"), m_infoFont); y += yoffset; break;
+        case DESIGN_VIEWMODE_TOP:
+            renderText(x, y, QString("View Mode: Top"), m_infoFont); y += yoffset; break;
+        case DESIGN_VIEWMODE_SIDE:
+            renderText(x, y, QString("View Mode: Side"), m_infoFont); y += yoffset; break;
+        case DESIGN_VIEWMODE_FRONT:
+            renderText(x, y, QString("View Mode: Front"), m_infoFont); y += yoffset; break;
+        }
+        renderText(x, y, QString("Operation Mode: %1").arg(m_opMode==DESIGN_OPMODE_PROJECTOR?"Projector":"View"), m_infoFont); y += yoffset;
+        renderText(x, y, QString("Translation Mode: %1").arg(m_transMode==DESIGN_TRANSMODE_LOCAL?"Local":"World"), m_infoFont); y += yoffset;
+        if (m_pModel->getSelectedChannel())
+            renderText(x, y, QString("Channel: %1").arg(m_pModel->getSelectedChannel()->getName()), m_infoFont); y += yoffset;
+
+#ifdef _DEBUG
+        renderText(x, y, QString("UpdateViews: %1").arg(m_pModel->m_updateViewsCount), m_infoFont); y += yoffset;
+        renderText(x, y, QString("UpdateOffscreen: %1").arg(m_pModel->m_updateOffscreenCount), m_infoFont); y += yoffset;
+#endif // _DEBUG
+    }
+}
+
+void QDesignViewWidget::setViewMode(DESIGN_VIEWMODE viewMode)
+{
+    if (m_viewMode == viewMode)
+        return;
+
+    if (viewMode == DESIGN_VIEWMODE_PERSPECTIVE)
+    {
+        setPerspective(true);
+        viewAll();
+    }
+    else if (viewMode == DESIGN_VIEWMODE_CENTER)
+    {
+        setPerspective(true);
+        setView(Vec3f(), Quatf(), 0.0f);
+    }
+    else
+    {
+        switch (viewMode)
+        {
+        case DESIGN_VIEWMODE_TOP:
+            setView(Vec3f(), makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-90.0f), Vec3f(1.0f, 0.0f, 0.0f))), 0.0f);
+            break;
+        case DESIGN_VIEWMODE_SIDE:
+            setView(Vec3f(), makeRot<Quatf>(AxisAnglef(Math::deg2Rad(90.0f), Vec3f(0.0f, 1.0f, 0.0f))), 0.0f);
+            break;
+        case DESIGN_VIEWMODE_FRONT:
+            setView(Vec3f(), Quatf(), 0.0f);
+            break;
+        }
+        setPerspective(false);
+        viewAll();
+    }
+
+    m_viewMode = viewMode;
+
+    updateGL();
+}
+
+DESIGN_VIEWMODE QDesignViewWidget::getViewMode() const
+{
+    return m_viewMode;
+}
+
+void QDesignViewWidget::setOpMode(DESIGN_OPMODE opMode)
+{
+    m_opMode = opMode;
+    updateGL();
+}
+
+DESIGN_OPMODE QDesignViewWidget::getOpMode() const
+{
+    return m_opMode;
+}
+
+void QDesignViewWidget::setTransMode(DESIGN_TRANSMODE transMode)
+{
+    m_transMode = transMode;
+    updateGL();
+}
+
+DESIGN_TRANSMODE QDesignViewWidget::getTransMode() const
+{
+    return m_transMode;
+}
+
+void QDesignViewWidget::setInfoVisible(bool bVisible)
+{
+    if (m_bInfoVisible != bVisible)
+    {
+        m_bInfoVisible = bVisible;
+        updateGL();
+        infoVisibilityChanged(bVisible);
+    }
+}
+
+bool QDesignViewWidget::isInfoVisible() const
+{
+    return m_bInfoVisible;
+}
+
+void QDesignViewWidget::keyReleaseEvent(QKeyEvent* pEvent)
+{
+    QGLViewerWidget::keyReleaseEvent(pEvent);
+
+    switch (pEvent->key())
+    {
+    case Qt::Key_I:
+        setInfoVisible(!isInfoVisible());
+        break;
+    case Qt::Key_F1:
+        setViewMode(DESIGN_VIEWMODE_PERSPECTIVE);
+        break;
+    case Qt::Key_F2:
+        setViewMode(DESIGN_VIEWMODE_CENTER);
+        break;
+    case Qt::Key_F3:
+        setViewMode(DESIGN_VIEWMODE_TOP);
+        break;
+    case Qt::Key_F4:
+        setViewMode(DESIGN_VIEWMODE_SIDE);
+        break;
+    case Qt::Key_F5:
+        setViewMode(DESIGN_VIEWMODE_FRONT);
+        break;
+    case Qt::Key_Space:
+        m_pModel->selectNextChannel();
+        break;
+    default:
+        break;
+    }
+
+    if (!m_pModel->getSelectedChannel())
+        return;
+
+    processChannelKeyEvent(m_pModel->getSelectedChannel(), pEvent);
+}
+
+void QDesignViewWidget::processChannelKeyEvent(Channel* pChannel, QKeyEvent* pEvent)
+{
+#if 1
+		Q_UNUSED(pChannel);
+		Q_UNUSED(pEvent);
+#else
+    if (!pChannel)
+        return;
+
+    bool bShift = (pEvent->modifiers() & Qt::ShiftModifier);
+#ifdef WIN32
+    bShift = (GetAsyncKeyState(VK_SHIFT)<0);
+#endif // WIN32
+    bool bCtrl = (pEvent->modifiers() & Qt::ControlModifier);
+//  bool bAlt = (pEvent->modifiers() & Qt::AltModifier);
+    bool bKeypad = (pEvent->modifiers() & Qt::KeypadModifier);
+#ifdef WIN32
+    bool bCapsLock = false; // <-- Careful, bCapsLock is not used.
+    bCapsLock = (GetAsyncKeyState(VK_CAPITAL) < 0);
+#endif // WIN32
+
+    float step = 1.0f;
+    if (bShift && bCtrl)
+        step = 0.01f;
+    else if (bShift || bCtrl)
+        step = 0.1f;
+
+    Frustum* pFrustum = pChannel->getProjector();
+    if (m_opMode == DESIGN_OPMODE_VIEW)
+        pFrustum = pChannel->getView();
+
+    ProjectionMatrix projMatrix = pFrustum->getProjectionMatrix();
+    TransformMatrix xformMatrix = pFrustum->getTransformMatrix();
+    gmtl::Vec3f pos = xformMatrix.getPosition();
+    gmtl::Vec3f rot = xformMatrix.getRotation();
+    gmtl::Quatf quatRot = gmtl::makeRot<gmtl::Quatf>(xformMatrix.getMatrix());
+
+    if (bKeypad)
+    {
+        switch (pEvent->key())
+        {
+        case Qt::Key_8:
+        case Qt::Key_Up:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1], pos[2]-0.1f*step));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(0.0f, 0.0f, -0.1f*step));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_2:
+        case Qt::Key_Down:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1], pos[2]+0.1f*step));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(0.0f, 0.0f, 0.1f*step));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_6:
+        case Qt::Key_Right:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0]+0.1f*step, pos[1], pos[2]));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(0.1f*step, 0.0f, 0.0f));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_4:
+        case Qt::Key_Left:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0]-0.1f*step, pos[1], pos[2]));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(-0.1f*step, 0.0f, 0.0f));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_9:
+        case Qt::Key_PageUp:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1]+0.1f*step, pos[2]));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(0.0f, 0.1f*step, 0.0f));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_3:
+        case Qt::Key_PageDown:
+            if (m_transMode == DESIGN_TRANSMODE_WORLD)
+                xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1]-0.1f*step, pos[2]));
+            else
+                xformMatrix.setPosition(pos + quatRot * gmtl::Vec3f(0.0f, -0.1f*step, 0.0f));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Plus:
+            projMatrix.setOffaxisY(projMatrix.getOffaxisY()-0.01f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        case Qt::Key_Minus:
+            projMatrix.setOffaxisY(projMatrix.getOffaxisY()+0.01f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        case Qt::Key_Asterisk:
+            projMatrix.setOffaxisX(projMatrix.getOffaxisX()+0.01f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        case Qt::Key_Slash:
+            projMatrix.setOffaxisX(projMatrix.getOffaxisX()-0.01f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        }
+    }
+    else
+    {
+        switch (pEvent->key())
+        {
+        case Qt::Key_PageUp:
+            xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1]+0.1f*step, pos[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_PageDown:
+            xformMatrix.setPosition(gmtl::Vec3f(pos[0], pos[1]-0.1f*step, pos[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Left:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0]+1.0f*step, rot[1], rot[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Right:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0]-1.0f*step, rot[1], rot[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Up:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0], rot[1]+1.0f*step, rot[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Down:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0], rot[1]-1.0f*step, rot[2]));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Home:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0], rot[1], rot[2]-1.0f*step));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_End:
+            xformMatrix.setRotation(gmtl::Vec3f(rot[0], rot[1], rot[2]+1.0f*step));
+            pFrustum->setTransformMatrix(xformMatrix);
+            break;
+        case Qt::Key_Comma:
+            projMatrix.setFOV(projMatrix.getFOV()-1.0f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        case Qt::Key_Period:
+            projMatrix.setFOV(projMatrix.getFOV()+1.0f*step);
+            pFrustum->setProjectionMatrix(projMatrix);
+            break;
+        case Qt::Key_Q:
+            if (m_opMode == DESIGN_OPMODE_PROJECTOR)
+                setOpMode(DESIGN_OPMODE_VIEW);
+            else
+                setOpMode(DESIGN_OPMODE_PROJECTOR);
+            break;
+        case Qt::Key_T:
+            if (m_transMode == DESIGN_TRANSMODE_LOCAL)
+                setTransMode(DESIGN_TRANSMODE_WORLD);
+            else
+                setTransMode(DESIGN_TRANSMODE_LOCAL);
+            break;
+        }
+    }
+#endif
+}
+
+void QDesignViewWidget::initFromDOMElement(const QDomElement& element)
+{
+    QGLViewerWidget::initFromDOMElement(element);
+
+    QDomElement display = element.firstChildElement("Display");
+    if (!display.isNull()) {
+        QString viewMode = display.attribute("viewMode", "projector");
+        if (viewMode == "perspective")
+            m_viewMode = DESIGN_VIEWMODE_PERSPECTIVE;
+        else if (viewMode == "center")
+            m_viewMode = DESIGN_VIEWMODE_CENTER;
+        else if (viewMode == "top")
+            m_viewMode = DESIGN_VIEWMODE_TOP;
+        else if (viewMode == "side")
+            m_viewMode = DESIGN_VIEWMODE_SIDE;
+        else if (viewMode == "front")
+            m_viewMode = DESIGN_VIEWMODE_FRONT;
+        if (display.attribute("opMode", "projector")=="projector")
+            m_opMode = DESIGN_OPMODE_PROJECTOR;
+        else
+            m_opMode = DESIGN_OPMODE_VIEW;
+        if (display.attribute("transMode", "local")=="local")
+            m_transMode = DESIGN_TRANSMODE_LOCAL;
+        else
+            m_transMode = DESIGN_TRANSMODE_WORLD;
+        m_bInfoVisible = (display.attribute("info", "true")=="true");
+    }
+}
+
+QDomElement QDesignViewWidget::domElement(QDomDocument& doc) const
+{
+    QDomElement de = QGLViewerWidget::domElement("DesignView", doc);
+    QDomElement display = de.firstChildElement("Display");
+    if (!display.isNull()) {
+        switch (m_viewMode) {
+        case DESIGN_VIEWMODE_PERSPECTIVE: display.setAttribute("viewMode", "perspective"); break;
+        case DESIGN_VIEWMODE_CENTER:      display.setAttribute("viewMode", "center"); break;
+        case DESIGN_VIEWMODE_TOP:         display.setAttribute("viewMode", "top"); break;
+        case DESIGN_VIEWMODE_SIDE:        display.setAttribute("viewMode", "side"); break;
+        case DESIGN_VIEWMODE_FRONT:       display.setAttribute("viewMode", "front"); break;
+        }
+        display.setAttribute("opMode", m_opMode==DESIGN_OPMODE_PROJECTOR?"projector":"view");
+        display.setAttribute("transMode", m_transMode==DESIGN_TRANSMODE_LOCAL?"local":"world");
+        display.setAttribute("info", m_bInfoVisible?"true":"false");
+    }
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWindow.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWindow.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QDesignViewWindow.cpp	(revision 4)
@@ -0,0 +1,428 @@
+#include "ProjectionModel.h"
+#include "Scene.h"
+#include "Screen.h"
+#include "Channel.h"
+#include "RSync.h"
+#include "Exporter.h"
+#include "GUIControler.h"
+
+#include "gui/QDesignViewWindow.h"
+
+#include "plugindialog.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QFileDialog>
+
+using namespace projection;
+
+QDesignViewWindow::QDesignViewWindow(QWidget* pParent, Qt::WFlags flags)
+    : QMainWindow(pParent, flags)
+{
+    ui.setupUi(this);
+
+    // initialize recent files list
+    for (unsigned int i=0; i<MAX_RECENT_FILES; ++i) {
+        m_pRecentFileActs[i] = new QAction(this);
+        m_pRecentFileActs[i]->setVisible(false);
+        connect(m_pRecentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
+    }
+
+    m_pSeparatorAct = ui.menuFile->addSeparator();
+    m_pSeparatorAct->setVisible(false);
+    for (unsigned int i=0; i<MAX_RECENT_FILES; ++i)
+        ui.menuFile->addAction(m_pRecentFileActs[i]);
+    ui.menuFile->addSeparator();
+    ui.menuFile->addAction(ui.actionFileExit);
+    ui.menuFile->addAction(ui.actionFileExitAll);
+
+    updateRecentFileActions();
+
+    // initialize toggle actions
+    ui.actionEditDesignDistortionMap->setCheckable(true);
+    ui.actionEditDesignBlendMap->setCheckable(true);
+    ui.actionEditDesignDistortionMap->setChecked(true);
+
+    ui.actionViewPerspective->setCheckable(true);
+    ui.actionViewCenter->setCheckable(true);
+    ui.actionViewTop->setCheckable(true);
+    ui.actionViewSide->setCheckable(true);
+    ui.actionViewFront->setCheckable(true);
+	ui.actionViewAxis->setCheckable(true);
+	ui.actionViewGrid->setCheckable(true);
+	ui.actionViewInfo->setCheckable(true);
+
+	ui.actionViewAxis->setChecked(ui.designViewWidget->isAxisVisible());
+	ui.actionViewGrid->setChecked(ui.designViewWidget->isGridVisible());
+	ui.actionViewInfo->setChecked(ui.designViewWidget->isInfoVisible());
+
+    QShortcut* pShortcut = new QShortcut(this);
+    pShortcut->setKey(Qt::Key_Escape);
+    pShortcut->setContext(Qt::WindowShortcut);
+    pShortcut->setEnabled(true);
+    connect(pShortcut, SIGNAL(activated()), this, SLOT(activateDesignView()));
+
+    statusBar();
+
+    ui.panelWidget->setMinimumWidth(240);
+    QList<int> sizes;
+    sizes << width()-240 << 240;
+    ui.splitter->setSizes(sizes);
+}
+
+QDesignViewWindow::~QDesignViewWindow()
+{
+}
+
+void QDesignViewWindow::setModel(ProjectionModel* pModel)
+{
+	m_pModel = pModel;
+	ui.designViewWidget->setModel(pModel);
+    ui.panelWidget->setModel(pModel);
+
+    if (m_pModel->getRSync()->isServer())
+        ui.actionFileSyncClients->setEnabled(true);
+    else
+        ui.actionFileSyncClients->setEnabled(false);
+    setCurrentFile("");
+}
+
+QGLWidget* QDesignViewWindow::getGLWidget() const
+{
+	return ui.designViewWidget;
+}
+
+QDesignViewWidget* QDesignViewWindow::getDesignView() const
+{
+    return ui.designViewWidget;
+}
+
+QPanelWidget* QDesignViewWindow::getPanel() const
+{
+    return ui.panelWidget;
+}
+
+void QDesignViewWindow::setCurrentFile(const QString& fileName)
+{
+    m_fileName = fileName;
+
+    QString title;
+    if (m_pModel->getRSync()->isServer())
+        title = QString(" : Server (%1:%2)").arg(m_pModel->getRSync()->getHostName()).arg(m_pModel->getRSync()->getPortNo());
+    else
+        title = QString(" : Client (%1:%2)").arg(m_pModel->getRSync()->getServerAddress()).arg(m_pModel->getRSync()->getPortNo());
+
+    if (m_fileName.isEmpty())
+        setWindowTitle(tr(APPLICATION_NAME) + title);
+    else
+        setWindowTitle(tr("%1 - %2").arg(QFileInfo(m_fileName).fileName()).arg(APPLICATION_NAME) + title);
+
+    if (!fileName.isEmpty())
+    {
+        QSettings settings("Orihalcon", APPLICATION_NAME);
+        QStringList files = settings.value("recentFileList").toStringList();
+        files.removeAll(m_fileName);
+        files.prepend(m_fileName);
+        while (files.size() > MAX_RECENT_FILES)
+            files.removeLast();
+        settings.setValue("recentFileList", files);
+        updateRecentFileActions();
+    }
+}
+
+void QDesignViewWindow::updateRecentFileActions()
+{
+    QSettings settings("Orihalcon", APPLICATION_NAME);
+    QStringList files = settings.value("recentFileList").toStringList();
+
+    int numRecentFiles = qMin(files.size(), (int)MAX_RECENT_FILES);
+
+    for (int i=0; i<numRecentFiles; ++i) {
+        QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName());
+        m_pRecentFileActs[i]->setText(text);
+        m_pRecentFileActs[i]->setData(files[i]);
+        m_pRecentFileActs[i]->setVisible(true);
+    }
+    for (int j=numRecentFiles; j<MAX_RECENT_FILES; ++j)
+        m_pRecentFileActs[j]->setVisible(false);
+
+    m_pSeparatorAct->setVisible(numRecentFiles > 0);
+}
+
+void QDesignViewWindow::openRecentFile()
+{
+    QAction* pAction = qobject_cast<QAction *>(sender());
+    if (pAction)
+        loadFile(pAction->data().toString());
+}
+
+bool QDesignViewWindow::loadFile(const QString& fileName)
+{
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    bool result = m_pModel->loadFile(fileName);
+    if (result)
+    {
+        setCurrentFile(fileName);
+        statusBar()->showMessage(tr("File loaded"), 2000);
+    }
+	else
+	{
+		QMessageBox::critical( this, "Could not load File", "An Error occured while parsing the project file.<br>It's impossible to continue, so starting an new empty project.");
+		on_actionFileNew_triggered();
+	}
+    QApplication::restoreOverrideCursor();
+    return result;
+}
+
+bool QDesignViewWindow::saveFile(const QString& fileName)
+{
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    bool result = m_pModel->saveFile(fileName);
+    if (result)
+    {
+        setCurrentFile(fileName);
+        statusBar()->showMessage(tr("File saved"), 2000);
+    }
+    QApplication::restoreOverrideCursor();
+    return result;
+}
+
+void QDesignViewWindow::on_actionFileNew_triggered()
+{
+    m_pModel->newFile();
+    setCurrentFile("");
+}
+
+void QDesignViewWindow::on_actionFileOpen_triggered()
+{
+    QString fileName = QFileDialog::getOpenFileName(
+        this, "Choose a file to open", QString(), "Projection setting files (*.xml)");
+    if (!fileName.isEmpty())
+    {
+        loadFile(fileName);
+    }
+}
+
+void QDesignViewWindow::on_actionFileSave_triggered()
+{
+    if (m_fileName.isEmpty())
+        on_actionFileSaveAs_triggered();
+    else
+        saveFile(m_fileName);
+}
+
+void QDesignViewWindow::on_actionFileSaveAs_triggered()
+{
+    QString fileName = QFileDialog::getSaveFileName(
+        this, "Choose a filename to save under", m_fileName, "Projection setting files (*.xml)");
+    if (!fileName.isEmpty())
+    {
+        QFileInfo fileInfo(fileName);
+        if (fileInfo.suffix().toLower() != "xml") {
+            fileName = fileInfo.absolutePath() + "/" + fileInfo.baseName() + ".xml";
+        }
+        saveFile(fileName);
+    }
+}
+
+void QDesignViewWindow::on_actionFileExportDataset_triggered()
+{
+    if (m_fileName.isEmpty()) {
+        QMessageBox::warning(this, APPLICATION_NAME,
+            tr("Save the current project before export data set."));
+        return;
+    }
+
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    m_pModel->getExporter()->exportDataset(m_fileName);
+    QApplication::restoreOverrideCursor();
+}
+
+void QDesignViewWindow::on_actionFileSyncClients_triggered()
+{
+    m_pModel->getRSync()->sendReloadSettings();
+}
+
+void QDesignViewWindow::on_actionFileExit_triggered()
+{
+    m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_DISCONNECT, "Disconnect");
+	close();
+}
+
+void QDesignViewWindow::on_actionFileExitAll_triggered()
+{
+    m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_END, "End");
+	close();
+}
+
+void QDesignViewWindow::on_actionEditDesignDistortionMap_triggered()
+{
+    m_pModel->setDesignMode(DESIGN_MODE_DISTORTIONMAP);
+}
+
+void QDesignViewWindow::on_actionEditDesignBlendMap_triggered()
+{
+    m_pModel->setDesignMode(DESIGN_MODE_BLENDMAP);
+}
+
+void QDesignViewWindow::on_actionEditPreference_triggered()
+{
+    m_pModel->getGUI()->showPreferenceDialog();
+}
+
+void QDesignViewWindow::on_actionViewPerspective_triggered()
+{
+    ui.designViewWidget->setViewMode(DESIGN_VIEWMODE_PERSPECTIVE);
+}
+
+void QDesignViewWindow::on_actionViewCenter_triggered()
+{
+    ui.designViewWidget->setViewMode(DESIGN_VIEWMODE_CENTER);
+}
+
+void QDesignViewWindow::on_actionViewTop_triggered()
+{
+    ui.designViewWidget->setViewMode(DESIGN_VIEWMODE_TOP);
+}
+
+void QDesignViewWindow::on_actionViewSide_triggered()
+{
+    ui.designViewWidget->setViewMode(DESIGN_VIEWMODE_SIDE);
+}
+
+void QDesignViewWindow::on_actionViewFront_triggered()
+{
+    ui.designViewWidget->setViewMode(DESIGN_VIEWMODE_FRONT);
+}
+
+void QDesignViewWindow::on_menuEdit_aboutToShow()
+{
+    ui.actionEditDesignDistortionMap->setChecked(m_pModel->getDesignMode() == DESIGN_MODE_DISTORTIONMAP);
+    ui.actionEditDesignBlendMap->setChecked(m_pModel->getDesignMode() == DESIGN_MODE_BLENDMAP);
+}
+
+void QDesignViewWindow::on_menuView_aboutToShow()
+{
+    ui.actionViewPerspective->setChecked(ui.designViewWidget->getViewMode()==DESIGN_VIEWMODE_PERSPECTIVE);
+    ui.actionViewCenter->setChecked(ui.designViewWidget->getViewMode()==DESIGN_VIEWMODE_CENTER);
+    ui.actionViewTop->setChecked(ui.designViewWidget->getViewMode()==DESIGN_VIEWMODE_TOP);
+    ui.actionViewSide->setChecked(ui.designViewWidget->getViewMode()==DESIGN_VIEWMODE_SIDE);
+    ui.actionViewFront->setChecked(ui.designViewWidget->getViewMode()==DESIGN_VIEWMODE_FRONT);
+}
+
+void QDesignViewWindow::on_actionViewAxis_triggered(bool checked)
+{
+	ui.designViewWidget->setAxisVisible(checked);
+    ui.designViewWidget->updateGL();
+	ui.actionViewAxis->setChecked(checked);
+}
+
+void QDesignViewWindow::on_designViewWidget_axisVisibilityChanged(bool bVisible)
+{
+	ui.actionViewAxis->setChecked(bVisible);
+}
+
+void QDesignViewWindow::on_actionViewGrid_triggered(bool checked)
+{
+	ui.designViewWidget->setGridVisible(checked);
+    ui.designViewWidget->updateGL();
+	ui.actionViewGrid->setChecked(checked);
+}
+
+void QDesignViewWindow::on_designViewWidget_gridVisibilityChanged(bool bVisible)
+{
+	ui.actionViewGrid->setChecked(bVisible);
+}
+
+void QDesignViewWindow::on_actionViewInfo_triggered(bool checked)
+{
+	ui.designViewWidget->setInfoVisible(checked);
+	ui.actionViewInfo->setChecked(checked);
+}
+
+void QDesignViewWindow::on_designViewWidget_infoVisibilityChanged(bool displayed)
+{
+	ui.actionViewInfo->setChecked(displayed);
+}
+
+void QDesignViewWindow::on_actionViewViewAll_triggered()
+{
+	ui.designViewWidget->viewAll();
+}
+
+void QDesignViewWindow::on_actionWindowSceneViewer_triggered()
+{
+	m_pModel->getGUI()->showSceneViewerWindow();
+}
+
+void QDesignViewWindow::on_actionWindowSceneDialog_triggered()
+{
+    ui.panelWidget->activateScene();
+}
+
+void QDesignViewWindow::on_actionWindowScreenDialog_triggered()
+{
+    ui.panelWidget->activateScreen();
+}
+
+void QDesignViewWindow::on_actionWindowChannelManager_triggered()
+{
+    ui.panelWidget->activateChannels();
+}
+
+void QDesignViewWindow::on_actionHelpHelp_triggered()
+{
+}
+
+void QDesignViewWindow::on_actionHelpPlugins_triggered()
+{
+		PluginDialog dialog(ProjectionModel::pluginsDir.path(), ProjectionModel::pluginFileNames, this);
+    dialog.exec();
+}
+
+void QDesignViewWindow::on_actionHelpAbout_triggered()
+{
+	QMessageBox::about(this, "Information", 
+		"<h2>" APPLICATION_NAME "</h2><br>"
+		"<nobr>version 1.0.99.Plugin by Toshiyuki Takahei, 2006</nobr><br>"
+        "<nobr>version " APPLICATION_VERSION "<br>by Torben Dannhauer, 2009</nobr>");
+}
+
+void QDesignViewWindow::on_actionHelpAbout_Qt_triggered()
+{
+	QMessageBox::aboutQt(this);
+}
+
+void QDesignViewWindow::activateDesignView()
+{
+    ui.designViewWidget->setFocus();
+}
+
+void QDesignViewWindow::closeEvent(QCloseEvent* pEvent)
+{
+    QMainWindow::closeEvent(pEvent);
+
+    m_pModel->getGUI()->closeAllWindows();
+}
+
+void QDesignViewWindow::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+		if (!element.firstChildElement("DesignView").isNull())
+			ui.designViewWidget->initFromDOMElement(element.firstChildElement("DesignView"));
+    }
+
+	ui.actionViewAxis->setChecked(ui.designViewWidget->isAxisVisible());
+	ui.actionViewGrid->setChecked(ui.designViewWidget->isGridVisible());
+	ui.actionViewInfo->setChecked(ui.designViewWidget->isInfoVisible());
+}
+
+QDomElement QDesignViewWindow::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+
+	de.appendChild(ui.designViewWidget->domElement(doc));
+
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QGLViewerWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QGLViewerWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QGLViewerWidget.cpp	(revision 4)
@@ -0,0 +1,440 @@
+#include <float.h>
+#include <QMouseEvent>
+
+#include "gui/QGLViewerWidget.h"
+
+#define INERTIA_MAX 5.0f
+#define INERTIA_THRESHOLD 0.2f
+
+using namespace gmtl;
+
+static void dom2vp(const QDomElement& parent, gmtl::Vec3f& center, gmtl::Quatf& rot, float& distance)
+{
+    if (parent.isNull())
+        return;
+
+    center[0] = parent.attribute("centerx", "0").toFloat();
+    center[1] = parent.attribute("centery", "0").toFloat();
+    center[2] = parent.attribute("centerz", "0").toFloat();
+    rot[0] = parent.attribute("rotx", "0").toFloat();
+    rot[1] = parent.attribute("roty", "0").toFloat();
+    rot[2] = parent.attribute("rotz", "0").toFloat();
+    rot[3] = parent.attribute("rotw", "1").toFloat();
+    distance = parent.attribute("distance", "1").toFloat();
+}
+
+static QDomElement vp2dom(QDomDocument& doc, const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
+{
+    QDomElement cm = doc.createElement("Camera");
+    cm.setAttribute("centerx", QString::number(center[0]));
+    cm.setAttribute("centery", QString::number(center[1]));
+    cm.setAttribute("centerz", QString::number(center[2]));
+    cm.setAttribute("rotx", QString::number(rot[0]));
+    cm.setAttribute("roty", QString::number(rot[1]));
+    cm.setAttribute("rotz", QString::number(rot[2]));
+    cm.setAttribute("rotw", QString::number(rot[3]));
+    cm.setAttribute("distance", QString::number(distance));
+    return cm;
+}
+
+QGLViewerWidget::QGLViewerWidget(QWidget* pParent, const QGLWidget* pShareWidget, Qt::WindowFlags f) : QGLWidget(pParent, pShareWidget, f)
+{
+    m_bPerspective = true;
+    m_fovy = 45.0f;
+    m_znear = 0.01f;
+    m_zfar = 100.0f;
+
+    m_bInertia = true;
+    m_animX = 0.0f;
+    m_animY = 0.0f;
+    m_bAnimating = false;
+
+    m_clearColor = QColor(64, 64, 64);
+    m_sceneSize = 10.0f;
+    m_bGridVisible = false;
+    m_bAxisVisible = false;
+    m_gridSize = 10.0f;
+    m_gridSubdiv = 10;
+
+    viewAll();
+
+    m_timer.setInterval(30);
+    connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
+    m_timer.start();
+
+    setFocusPolicy(Qt::StrongFocus);
+}
+
+void QGLViewerWidget::setView(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
+{
+    m_center = center;
+    m_rot = rot;
+    m_distance = distance;
+    m_matrix = makeTrans<Matrix44f>(m_center) * makeRot<Matrix44f>(m_rot) * makeTrans<Matrix44f>(Vec3f(0.0f, 0.0f, m_distance));
+    invert(m_matrix);
+
+    emit cameraChanged(center, rot, distance);
+}
+
+void QGLViewerWidget::init()
+{
+}
+
+void QGLViewerWidget::draw()
+{
+}
+
+void QGLViewerWidget::idle()
+{
+}
+
+void QGLViewerWidget::stop()
+{
+    m_pivotCenter = m_center;
+    m_pivotRot = m_rot;
+    m_pivotDistance = m_distance;
+    m_pivotOrthoScale = m_orthoScale;
+    m_animX = 0.0f;
+    m_animY = 0.0f;
+    m_bAnimating = false;
+}
+
+void QGLViewerWidget::centerView()
+{
+    stop();
+    m_center = Vec3f(0.0f, 0.0f, 0.0f);
+    m_rot = Quatf();
+    m_distance = 0.0f;
+    m_orthoScale = 0.25f;
+    setView(m_center, m_rot, m_distance);
+    updateGL();
+}
+
+void QGLViewerWidget::viewAll()
+{
+    stop();
+    m_center = Vec3f(0.0f, 0.0f, 0.0f);
+    if (m_bPerspective)
+        m_distance = m_sceneSize * 0.5f;
+    else
+        m_distance = 0.0f;
+    m_orthoScale = 0.25f;
+    setView(m_center, m_rot, m_distance);
+    updateGL();
+}
+
+void QGLViewerWidget::drawGrid()
+{
+    if (m_gridSubdiv == 0)
+        return;
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_BLEND);
+    glEnable(GL_DEPTH_TEST);
+    glLineWidth(1.0f);
+    glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
+    glBegin(GL_LINES);
+    for (int x=0; x<m_gridSubdiv+1; ++x)
+    {
+        glVertex3f(-m_gridSize/2.0f+m_gridSize/m_gridSubdiv*x, 0.0f, -m_gridSize/2.0f);
+        glVertex3f(-m_gridSize/2.0f+m_gridSize/m_gridSubdiv*x, 0.0f,  m_gridSize/2.0f);
+    }
+    for (int y=0; y<m_gridSubdiv+1; ++y)
+    {
+        glVertex3f(-m_gridSize/2.0f, 0.0f, -m_gridSize/2.0f+m_gridSize/m_gridSubdiv*y);
+        glVertex3f( m_gridSize/2.0f, 0.0f, -m_gridSize/2.0f+m_gridSize/m_gridSubdiv*y);
+    }
+    glEnd();
+    glPopAttrib();
+}
+
+void QGLViewerWidget::drawAxis()
+{
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_BLEND);
+    glEnable(GL_DEPTH_TEST);
+    glLineWidth(3.0f);
+    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+    glBegin(GL_LINES);
+    glVertex3f(0.0f, 0.0f, 0.0f);
+    glVertex3f(m_gridSize*0.6f, 0.0f, 0.0f);
+    glEnd();
+    glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+    glBegin(GL_LINES);
+    glVertex3f(0.0f, 0.0f, 0.0f);
+    glVertex3f(0.0f, m_gridSize*0.6f, 0.0f);
+    glEnd();
+    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
+    glBegin(GL_LINES);
+    glVertex3f(0.0f, 0.0f, 0.0f);
+    glVertex3f(0.0f, 0.0f, m_gridSize*0.6f);
+    glEnd();
+    glPopAttrib();
+}
+
+void QGLViewerWidget::initializeGL()
+{
+    init();
+}
+
+void QGLViewerWidget::paintGL()
+{
+    glViewport(0, 0, width(), height());
+
+    glClearColor((float)m_clearColor.red() / 255.0f,
+                 (float)m_clearColor.green() / 255.0f,
+                 (float)m_clearColor.blue() / 255.0f,
+                 1.0f);
+                 
+    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+
+    float aspect = 1.0f;
+    if (height() > 0)
+        aspect = (float)width()/height();
+    if (m_bPerspective)
+        gluPerspective(m_fovy, aspect, m_znear, m_zfar);
+    else
+    {
+        float size = m_sceneSize * m_orthoScale;
+        glOrtho(-size*aspect, size*aspect, -size, size, -m_sceneSize*4.0f, m_sceneSize*4.0f);
+    }
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadMatrixf(m_matrix.getData());
+
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    Vec3f pos = Vec3f(1.0f, 1.0f, 1.0f);
+    if (!_isnan(m_rot[0]))
+        pos = m_rot * pos;
+    GLfloat lposition[] = { pos[0], pos[1], pos[2], 0.0f };
+    GLfloat lambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
+    GLfloat ldiffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
+    glLightfv(GL_LIGHT0, GL_POSITION, lposition);
+    glLightfv(GL_LIGHT0, GL_AMBIENT, lambient);
+    glLightfv(GL_LIGHT0, GL_DIFFUSE, ldiffuse);
+
+    glEnable(GL_DEPTH_TEST);
+    glEnable(GL_COLOR_MATERIAL);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    draw();
+
+    glDisable(GL_LIGHTING);
+
+    if (m_bGridVisible)
+        drawGrid();
+
+    if (m_bAxisVisible)
+        drawAxis();
+
+    glFlush();
+}
+
+void QGLViewerWidget::mousePressEvent(QMouseEvent* pEvent)
+{
+    m_timer.stop();
+
+    stop();
+
+    m_lastMousePos = pEvent->pos();
+    m_lastTime = QTime::currentTime();
+
+    setMouseTracking(true);
+}
+
+void QGLViewerWidget::mouseMoveEvent(QMouseEvent* pEvent)
+{
+    if (m_bPerspective && (pEvent->buttons() & Qt::LeftButton))
+    {
+        float delta = (float)m_lastTime.msecsTo(QTime::currentTime()) / 1000.0f;
+        float deltaX = ((float)(pEvent->x()-m_lastMousePos.x())/width()*90.0f) / 180.0f * Math::PI;
+        float deltaY = ((float)(pEvent->y()-m_lastMousePos.y())/height()*90.0f) / 180.0f * Math::PI;
+        if (delta != 0.0f && (fabs(deltaX / delta) > INERTIA_THRESHOLD || fabs(deltaY / delta) > INERTIA_THRESHOLD))
+        {
+            m_animX = deltaX / delta;
+            m_animY = deltaY / delta;
+            float length = sqrt(m_animX*m_animX+m_animY*m_animY);
+            if (length > INERTIA_MAX)
+            {
+                m_animX = m_animX / length * INERTIA_MAX;
+                m_animY = m_animY / length * INERTIA_MAX;
+            }
+        }
+        else
+        {
+            m_animX = 0.0f;
+            m_animY = 0.0f;
+        }
+        m_rot = m_pivotRot * make<Quatf>(AxisAnglef(-deltaX, Vec3f(0.0f, 1.0f, 0.0f))) *
+                             make<Quatf>(AxisAnglef(-deltaY, Vec3f(1.0f, 0.0f, 0.0f)));
+    }
+    else if (pEvent->buttons() & Qt::MidButton ||
+             (!m_bPerspective && pEvent->buttons() & Qt::LeftButton))
+    {
+        float deltaX = (float)(pEvent->x()-m_lastMousePos.x())/width();
+        float deltaY = (float)(pEvent->y()-m_lastMousePos.y())/height();
+        Vec3f panX = m_rot * Vec3f(-deltaX, 0.0f, 0.0f);
+        Vec3f panY = m_rot * Vec3f(0.0f, deltaY, 0.0f);
+        m_center = m_pivotCenter + panX + panY;
+    }
+    else if (m_bPerspective && (pEvent->buttons() & Qt::RightButton))
+    {
+        if (m_distance > 0.0f)
+        {
+            m_distance = m_pivotDistance - m_pivotDistance * (float)(pEvent->y()-m_lastMousePos.y())/height() * 1.0f;
+            if (m_distance < m_znear*2.0f)
+                m_distance = m_znear*2.0f;
+        }
+    }
+    else if (!m_bPerspective && (pEvent->buttons() & Qt::RightButton))
+    {
+        m_orthoScale = m_pivotOrthoScale - m_pivotOrthoScale * (float)(pEvent->y()-m_lastMousePos.y())/height() * 1.0f;
+        if (m_orthoScale < 0.01f)
+            m_orthoScale = 0.01f;
+    }
+
+    setView(m_center, m_rot, m_distance);
+    m_lastTime = QTime::currentTime();
+
+    updateGL();
+}
+
+void QGLViewerWidget::mouseReleaseEvent(QMouseEvent* pEvent)
+{
+    Q_UNUSED(pEvent);
+
+    if (m_lastTime.msecsTo(QTime::currentTime()) > 50 || !m_bInertia)
+    {
+        m_animX = 0.0f;
+        m_animY = 0.0f;
+        m_bAnimating = false;
+    }
+    if (m_animX != 0.0f || m_animY != 0.0f)
+        m_bAnimating = true;
+
+    setMouseTracking(false);
+
+    m_timer.start();
+}
+
+void QGLViewerWidget::wheelEvent(QWheelEvent* pEvent)
+{
+    if (m_bPerspective)
+    {
+        if (pEvent->delta() > 0.0f)
+            setView(m_center, m_rot, m_distance * 1.1f);
+        else
+            setView(m_center, m_rot, m_distance / 1.1f);
+    }
+    else
+    {
+        if (pEvent->delta() > 0.0f)
+            m_orthoScale *= 1.1f;
+        else
+            m_orthoScale /= 1.1f;
+        if (m_orthoScale < 0.01f)
+            m_orthoScale = 0.01f;
+    }
+
+    updateGL();
+}
+
+void QGLViewerWidget::keyReleaseEvent(QKeyEvent* pEvent)
+{
+    QGLWidget::keyReleaseEvent(pEvent);
+
+	switch (pEvent->key())
+	{
+	case Qt::Key_A:
+        setAxisVisible(!m_bAxisVisible);
+        updateGL();
+		break;
+	case Qt::Key_G:
+        setGridVisible(!m_bGridVisible);
+        updateGL();
+		break;
+	case Qt::Key_R:
+        viewAll();
+		break;
+	default:
+		return;
+	}
+}
+
+void QGLViewerWidget::timeout()
+{
+    if (m_bAnimating)
+    {
+        float delta = (float)m_lastTime.msecsTo(QTime::currentTime()) / 1000.0f;
+        Quatf deltaRot = 
+            make<Quatf>(AxisAnglef(-m_animX*delta, Vec3f(0.0f, 1.0f, 0.0f))) *
+            make<Quatf>(AxisAnglef(-m_animY*delta, Vec3f(1.0f, 0.0f, 0.0f)));
+        Quatf rot = m_rot * deltaRot;
+        if (!_isnan(rot[0]))
+            setView(m_center, rot, m_distance);
+        m_lastTime = QTime::currentTime();
+    }
+
+    idle();
+
+    if (m_bAnimating)
+        updateGL();
+}
+
+void QGLViewerWidget::initFromDOMElement(const QDomElement& element)
+{
+	if (!element.isNull())
+	{
+		QDomElement camera = element.firstChildElement("Camera");
+        dom2vp(camera, m_center, m_rot, m_distance);
+        m_bPerspective = (element.attribute("perspective", "true")=="true");
+        m_fovy = element.attribute("fovy", QString::number(45.0f)).toFloat();
+        m_orthoScale = element.attribute("orthoScale", QString::number(0.25f)).toFloat();
+        m_znear = element.attribute("near", QString::number(0.01f)).toFloat();
+        m_zfar = element.attribute("far", QString::number(100.0f)).toFloat();
+        m_bInertia = (element.attribute("inertia", "true")=="true");
+        m_clearColor = QColor(element.attribute("clearColor", QColor(64, 64, 64).name()));
+        m_bGridVisible = (element.attribute("grid", "true")=="true");
+        m_bAxisVisible = (element.attribute("axis", "true")=="true");
+        m_sceneSize = element.attribute("sceneSize", QString::number(10.0f)).toFloat();
+        if (!parentWidget())
+        {
+            move(element.attribute("x", QString::number(x())).toInt(), element.attribute("y", QString::number(y())).toInt());
+            resize(element.attribute("width", QString::number(width())).toInt(), element.attribute("height", QString::number(height())).toInt());
+        }
+        setView(m_center, m_rot, m_distance);
+        stop();
+	}
+}
+
+QDomElement QGLViewerWidget::domElement(const QString& name, QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement(name);
+    de.appendChild(vp2dom(doc, m_center, m_rot, m_distance));
+    de.setAttribute("perspective", m_bPerspective?"true":"false");
+    de.setAttribute("fovy", m_fovy);
+    de.setAttribute("orthoScale", m_orthoScale);
+    de.setAttribute("near", m_znear);
+    de.setAttribute("far", m_zfar);
+    de.setAttribute("inertia", m_bInertia?"true":"false");
+    de.setAttribute("clearColor", m_clearColor.name());
+    de.setAttribute("grid", m_bGridVisible?"true":"false");
+    de.setAttribute("axis", m_bAxisVisible?"true":"false");
+    de.setAttribute("sceneSize", m_sceneSize);
+    if (!parentWidget())
+    {
+        de.setAttribute("x", x());
+        de.setAttribute("y", y());
+        de.setAttribute("width", width());
+        de.setAttribute("height", height());
+    }
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QPanelWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QPanelWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QPanelWidget.cpp	(revision 4)
@@ -0,0 +1,79 @@
+#include "ProjectionModel.h"
+#include "gui/QChannelManagerWidget.h"
+#include "gui/QChannelWidget.h"
+#include "gui/QScreenWidget.h"
+#include "gui/QSceneWidget.h"
+#include "gui/QPanelWidget.h"
+
+using namespace projection;
+
+QPanelWidget::QPanelWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+
+    m_pModel = NULL;
+}
+
+QPanelWidget::~QPanelWidget()
+{
+}
+
+void QPanelWidget::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+
+    ui.channelManager->setModel(m_pModel);
+    ui.screen->setScreen(m_pModel->getScreen());
+    ui.scene->setScene(m_pModel->getScene());
+
+    updateGUI();
+}
+
+void QPanelWidget::selectChannel(Channel* pChannel)
+{
+    if (ui.channelManager->getSelectedChannel() != m_pModel->getChannelIndex(pChannel))
+        ui.channelManager->selectChannel(m_pModel->getChannelIndex(pChannel));
+    if (ui.channel->getChannel() != pChannel) {
+        ui.channel->setChannel(pChannel);
+        ui.channel->updateGUI();
+    }
+}
+
+void QPanelWidget::activateChannels()
+{
+    ui.tabWidget->setCurrentIndex(0);
+}
+
+void QPanelWidget::activateScreen()
+{
+    ui.tabWidget->setCurrentIndex(1);
+}
+
+void QPanelWidget::activateScene()
+{
+    ui.tabWidget->setCurrentIndex(2);
+}
+
+void QPanelWidget::updateChannelNames()
+{
+    ui.channelManager->updateChannelNamesGUI();
+}
+
+void QPanelWidget::updateChannels()
+{
+    ui.channelManager->updateGUI();
+}
+
+void QPanelWidget::updateCurrentChannel()
+{
+    ui.channel->updateGUI();
+}
+
+void QPanelWidget::updateGUI()
+{
+    ui.channelManager->updateGUI();
+    ui.channel->updateGUI();
+    ui.screen->updateGUI();
+    ui.scene->updateGUI();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QPreferenceDialog.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QPreferenceDialog.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QPreferenceDialog.cpp	(revision 4)
@@ -0,0 +1,157 @@
+#include "ProjectionModel.h"
+#include "Scene.h"
+#include "Screen.h"
+#include "RSync.h"
+#include "Exporter.h"
+#include "GUIControler.h"
+#include "gui/Defines.h"
+#include "gui/QDesignViewWindow.h"
+#include "gui/QDesignViewWidget.h"
+#include "gui/QPreferenceDialog.h"
+
+using namespace projection;
+
+QPreferenceDialog::QPreferenceDialog(QWidget* pParent, Qt::WFlags flags)
+    : QDialog(pParent, flags)
+{
+    ui.setupUi(this);
+    setFixedSize(sizeHint());
+
+    m_pModel = NULL;
+}
+
+QPreferenceDialog::~QPreferenceDialog()
+{
+}
+
+void QPreferenceDialog::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+    if (m_pModel->getRSync()->isServer())
+        m_pDesignView = ((QDesignViewWindow*)m_pModel->getGUI()->getMainWindow())->getDesignView();
+
+    updateGUI();
+}
+
+void QPreferenceDialog::updateGUI()
+{
+    if (m_pModel)
+    {
+        ui.gridSizeEdit->setText(formatValue(m_pDesignView->gridSize()));
+        ui.gridSubdivSpinBox->setValue(m_pDesignView->gridSubdivision());
+
+        ui.bufferWidthComboBox->setCurrentIndex(ui.bufferWidthComboBox->findText(QString::number(m_pModel->getScreen()->getBufferWidth())));
+        ui.bufferHeightComboBox->setCurrentIndex(ui.bufferHeightComboBox->findText(QString::number(m_pModel->getScreen()->getBufferHeight())));
+
+		// If the export_width is not in the combo, we add the item.
+		int index_width = ui.exportWidthComboBox->findText(QString::number(m_pModel->getExporter()->getExportWidth()));
+		if (-1==index_width)
+		{
+		    int nb_items=ui.exportWidthComboBox->count();
+			ui.exportWidthComboBox->insertItem (nb_items, QString::number(m_pModel->getExporter()->getExportWidth()));
+	        ui.exportWidthComboBox->setCurrentIndex(nb_items);
+		}
+		else
+		{
+		    ui.exportWidthComboBox->setCurrentIndex(index_width);
+		}
+
+		// Same thing for the export_heith: if it is not in the combo, we add the item.
+		int index_height = ui.exportHeightComboBox->findText(QString::number(m_pModel->getExporter()->getExportHeight()));
+		if (-1==index_height)
+		{
+			int nb_items=ui.exportHeightComboBox->count();
+			ui.exportHeightComboBox->insertItem (nb_items, QString::number(m_pModel->getExporter()->getExportHeight()));
+			ui.exportHeightComboBox->setCurrentIndex(nb_items);
+		}
+		else
+		{
+			ui.exportHeightComboBox->setCurrentIndex(index_height);
+        }
+
+        ui.softEdgeCheckBox->setChecked(m_pModel->getExporter()->getSoftEdge());
+        ui.blendEdgeWidthSpinBox->setValue(m_pModel->getExporter()->getBlendEdgeWidth());
+        ui.blendEdgeExponentEdit->setText(QString::number(m_pModel->getExporter()->getBlendEdgeExponent()));
+        ui.exportDistortMapPatternEdit->setText(m_pModel->getExporter()->getDistortMapFileNamePattern());
+        ui.exportBlendMapPatternEdit->setText(m_pModel->getExporter()->getBlendMapFileNamePattern());
+        ui.exportViewMatrixPatternEdit->setText(m_pModel->getExporter()->getViewMatrixFileNamePattern());
+    }
+}
+
+void QPreferenceDialog::on_gridSizeEdit_editingFinished()
+{
+    if (m_pModel && m_pDesignView->gridSize() != ui.gridSizeEdit->text().toFloat()) {
+		m_pDesignView->setGridSize(ui.gridSizeEdit->text().toFloat());
+        m_pDesignView->updateGL();
+    }
+}
+
+void QPreferenceDialog::on_gridSubdivSpinBox_valueChanged(int value)
+{
+    if (m_pModel && m_pDesignView->gridSubdivision() != value) {
+		m_pDesignView->setGridSubdivision(value);
+        m_pDesignView->updateGL();
+    }
+}
+
+void QPreferenceDialog::on_bufferWidthComboBox_activated(int)
+{
+    if (m_pModel)
+        m_pModel->getScreen()->setBufferSize(ui.bufferWidthComboBox->currentText().toInt(),
+                                             ui.bufferHeightComboBox->currentText().toInt());
+}
+
+void QPreferenceDialog::on_bufferHeightComboBox_activated(int)
+{
+    if (m_pModel)
+        m_pModel->getScreen()->setBufferSize(ui.bufferWidthComboBox->currentText().toInt(),
+                                             ui.bufferHeightComboBox->currentText().toInt());
+}
+
+void QPreferenceDialog::on_exportWidthComboBox_activated(int)
+{
+	if (m_pModel)
+		m_pModel->getExporter()->setExportWidth(ui.exportWidthComboBox->currentText().toInt());
+}
+
+void QPreferenceDialog::on_exportHeightComboBox_activated(int)
+{
+	if (m_pModel)
+		m_pModel->getExporter()->setExportHeight(ui.exportHeightComboBox->currentText().toInt());
+}
+
+void QPreferenceDialog::on_softEdgeCheckBox_toggled(bool checked)
+{
+	if (m_pModel)
+		m_pModel->getExporter()->setSoftEdge(checked);
+}
+
+void QPreferenceDialog::on_blendEdgeWidthSpinBox_valueChanged(int value)
+{
+	if (m_pModel)
+		m_pModel->getExporter()->setBlendEdgeWidth(value);
+}
+
+void QPreferenceDialog::on_blendEdgeExponentEdit_editingFinished()
+{
+	if (m_pModel)
+		m_pModel->getExporter()->setBlendEdgeExponent(ui.blendEdgeExponentEdit->text().toFloat());
+}
+
+void QPreferenceDialog::on_exportDistortMapPatternEdit_editingFinished()
+{
+    if (m_pModel)
+        m_pModel->getExporter()->setDistortMapFileNamePattern(ui.exportDistortMapPatternEdit->text());
+}
+
+void QPreferenceDialog::on_exportBlendMapPatternEdit_editingFinished()
+{
+    if (m_pModel)
+        m_pModel->getExporter()->setBlendMapFileNamePattern(ui.exportBlendMapPatternEdit->text());
+}
+
+void QPreferenceDialog::on_exportViewMatrixPatternEdit_editingFinished()
+{
+    if (m_pModel)
+        m_pModel->getExporter()->setViewMatrixFileNamePattern(ui.exportViewMatrixPatternEdit->text());
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QProjectionMatrixWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QProjectionMatrixWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QProjectionMatrixWidget.cpp	(revision 4)
@@ -0,0 +1,96 @@
+#include "gui/Defines.h"
+#include "gui/QProjectionMatrixWidget.h"
+
+using namespace projection;
+
+QProjectionMatrixWidget::QProjectionMatrixWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+    m_bStopSlot = false;
+}
+
+QProjectionMatrixWidget::~QProjectionMatrixWidget()
+{
+}
+
+void QProjectionMatrixWidget::setMatrix(const ProjectionMatrix& matrix)
+{
+    if (m_bStopSlot) return;
+
+    ui.fovEdit->setText(formatValue(matrix.getFOV()));
+	ui.aspectRatioEdit->setText(QString::number(matrix.getAspectRatio(), 'g'));
+    ui.nearEdit->setText(QString::number(matrix.getNear(), 'g'));
+    ui.farEdit->setText(QString::number(matrix.getFar(), 'g'));
+    ui.offaxisXEdit->setText(formatValue(matrix.getOffaxisX()));
+    ui.offaxisYEdit->setText(formatValue(matrix.getOffaxisY()));
+
+//    checkValueChanged();
+    m_matrix = matrix;
+}
+
+ProjectionMatrix QProjectionMatrixWidget::getMatrix() const
+{
+    return m_matrix;
+}
+
+void QProjectionMatrixWidget::clear()
+{
+    ui.fovEdit->setText("");
+    ui.aspectRatioEdit->setText("");
+    ui.nearEdit->setText("");
+    ui.farEdit->setText("");
+    ui.offaxisXEdit->setText("");
+    ui.offaxisYEdit->setText("");
+    m_matrix = ProjectionMatrix();
+}
+
+void QProjectionMatrixWidget::checkValueChanged()
+{
+    ProjectionMatrix matrix;
+
+    matrix.setFOV(ui.fovEdit->text().toFloat());
+    matrix.setAspectRatio(ui.aspectRatioEdit->text().toFloat());
+    matrix.setNear(ui.nearEdit->text().toFloat());
+    matrix.setFar(ui.farEdit->text().toFloat());
+    matrix.setOffaxisX(ui.offaxisXEdit->text().toFloat());
+    matrix.setOffaxisY(ui.offaxisYEdit->text().toFloat());
+
+    if (m_matrix != matrix)
+    {
+        m_matrix = matrix;
+        m_bStopSlot = true;
+        emit matrixChanged(m_matrix);
+        m_bStopSlot = false;
+    }
+}
+
+void QProjectionMatrixWidget::on_fovEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QProjectionMatrixWidget::on_aspectRatioEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QProjectionMatrixWidget::on_nearEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QProjectionMatrixWidget::on_farEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QProjectionMatrixWidget::on_offaxisXEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QProjectionMatrixWidget::on_offaxisYEdit_editingFinished()
+{
+    checkValueChanged();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QProjectorWindow.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QProjectorWindow.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QProjectorWindow.cpp	(revision 4)
@@ -0,0 +1,263 @@
+#include "ProjectionModel.h"
+#include "Channel.h"
+#include "Screen.h"
+#include "Warp.h"
+#include "RSync.h"
+#include "GUIControler.h"
+#include "gui/QProjectorWindow.h"
+
+#include <QtOpenGL>
+
+using namespace projection;
+
+bool QProjectorWindow::m_bInitialized = false;
+
+QProjectorWindow::QProjectorWindow(QWidget* pParent, QGLWidget* pSharedWidget, Qt::WFlags flag) : QGLWidget(pParent, pSharedWidget, flag|Qt::Window)
+{
+    m_pModel = NULL;
+    m_pChannel = NULL;
+
+    m_blendChannelIndex = 0;
+
+    resize(640, 480);
+
+    m_overlayFont.setFamily("Helvetica");
+    m_overlayFont.setPointSize(64);
+
+    m_infoFont.setFamily("Helvetica");
+    m_infoFont.setPointSize(14);
+
+    setFocusPolicy(Qt::StrongFocus);
+}
+
+QProjectorWindow::~QProjectorWindow()
+{
+}
+
+void QProjectorWindow::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+}
+
+void QProjectorWindow::setChannel(Channel* pChannel)
+{
+    m_pChannel = pChannel;
+	updateTitle();
+	updateGL();
+}
+
+void QProjectorWindow::updateTitle()
+{
+	if (m_pChannel)
+		setWindowTitle(m_pChannel->getName() + " - Projector Window");
+}
+
+void QProjectorWindow::initializeGL()
+{
+    if (!m_pModel->getRSync()->isServer() && m_bInitialized)
+    {
+        m_bInitialized = true;
+    }
+
+    glBlendFunc(GL_ONE, GL_ONE);
+    glClearColor(0.0, 0.0, 0.0, 0.0);
+}
+
+void QProjectorWindow::resizeGL(int width, int height)
+{
+    glViewport(0, 0, width, height);
+}
+
+void QProjectorWindow::paintGL()
+{
+    m_pModel->setRenderContext(this);
+
+    if (m_pChannel)
+    {
+        if (m_pModel->getDesignMode() == DESIGN_MODE_DISTORTIONMAP)
+            m_pChannel->draw(CHANNEL_DRAWMODE_DESIGN_DISTORTIONMAP);
+        else
+            m_pChannel->draw(CHANNEL_DRAWMODE_DESIGN_BLENDMAP);
+
+        if (m_pChannel->getOverlayName())
+        {
+            QFontMetrics fontMet(m_overlayFont);
+            renderText((width()-fontMet.width(m_pChannel->getName()))/2, (height()+fontMet.height()/2)/2, m_pChannel->getName(), m_overlayFont, 3000);
+        }
+
+        if (m_pModel->getRSync()->isServer() && m_pModel->getDesignMode() == DESIGN_MODE_BLENDMAP)
+        {
+            glPushAttrib(GL_CURRENT_BIT);
+            glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+            Channel* pChannel = m_pModel->getChannel(m_blendChannelIndex);
+            if (pChannel)
+                renderText(16, 32, QString("%1 Blend factor : %2").arg(pChannel->getName()).arg(QString::number(m_pChannel->getBlendFactor(pChannel->getName()), 'f', 2)), m_infoFont, 4000);
+            renderText(16, 64, QString("[Space] : Select channel to edit blend factor."), m_infoFont, 4000);
+            renderText(16, 88, QString("[B] : Brighten the selected channel."), m_infoFont, 4000);
+            renderText(16, 112, QString("[D] : Darken the selected channel."), m_infoFont, 4000);
+            glPopAttrib();
+        }
+    }
+}
+
+void QProjectorWindow::keyReleaseEvent(QKeyEvent* pEvent)
+{
+    switch (pEvent->key())
+	{
+	case Qt::Key_Return:
+		if (pEvent->modifiers() & Qt::AltModifier)
+		{
+			if (!isFullScreen())
+				showFullScreen();
+			else
+				showNormal();
+		}
+		break;
+	case Qt::Key_Escape:
+        if (!m_pModel->getRSync()->isServer()) {
+            qApp->closeAllWindows();
+    		return;
+        }
+        else
+            close();
+        break;
+	case Qt::Key_Space:
+        if (m_pModel) {
+            m_blendChannelIndex++;
+            if (m_blendChannelIndex >= m_pModel->getNumChannels())
+                m_blendChannelIndex = 0;
+            updateGL();
+        }
+        break;
+	case Qt::Key_B:
+        if (m_pModel) {
+            Channel* pChannel = m_pModel->getChannel(m_blendChannelIndex);
+            if (pChannel)
+            {
+                float blendFactor = m_pChannel->getBlendFactor(pChannel->getName());
+		        if ((pEvent->modifiers() & Qt::ShiftModifier) ||
+                    (pEvent->modifiers() & Qt::ControlModifier))
+                    blendFactor += 0.01f;
+                else
+                    blendFactor += 0.1f;
+                if (blendFactor > 1.0f)
+                    blendFactor = 1.0f;
+                m_pChannel->setBlendFactor(pChannel->getName(), blendFactor);
+                updateGL();
+            }
+        }
+        break;
+	case Qt::Key_D:
+        if (m_pModel) {
+            Channel* pChannel = m_pModel->getChannel(m_blendChannelIndex);
+            if (pChannel)
+            {
+                float blendFactor = m_pChannel->getBlendFactor(pChannel->getName());
+		        if ((pEvent->modifiers() & Qt::ShiftModifier) ||
+                    (pEvent->modifiers() & Qt::ControlModifier))
+                    blendFactor -= 0.01f;
+                else
+                    blendFactor -= 0.1f;
+                if (blendFactor < 0.0f)
+                    blendFactor = 0.0f;
+                m_pChannel->setBlendFactor(pChannel->getName(), blendFactor);
+                updateGL();
+            }
+        }
+        break;
+	}
+
+    if (m_pModel->getRSync()->isServer())
+    {
+        m_pModel->getGUI()->processChannelKeyEvent(m_pChannel, pEvent);
+    }
+}
+
+void QProjectorWindow::mousePressEvent(QMouseEvent* pEvent)
+{
+    if (m_pChannel)
+    {
+        if (m_pChannel->getCurrentWarp()->pick(pEvent->x(), pEvent->y()))
+        	updateGL();
+    }
+}
+
+void QProjectorWindow::mouseMoveEvent(QMouseEvent* pEvent)
+{
+    if (pEvent->buttons() == Qt::LeftButton && m_pChannel)
+    {
+        if (m_pChannel->getCurrentWarp()->drag(pEvent->x(), pEvent->y())) {
+            m_pChannel->updateData();
+        	updateGL();
+        }
+    }
+}
+
+void QProjectorWindow::wheelEvent(QWheelEvent* pEvent)
+{
+    if (m_pChannel)
+    {
+        if (pEvent->delta() > 0)
+            m_pChannel->getCurrentWarp()->setZoom(m_pChannel->getCurrentWarp()->getZoom()/1.2f);
+        else
+            m_pChannel->getCurrentWarp()->setZoom(m_pChannel->getCurrentWarp()->getZoom()*1.2f);
+        updateGL();
+    }
+}
+
+void QProjectorWindow::closeEvent(QCloseEvent* pEvent)
+{
+    if (m_pChannel)
+        m_pChannel->clearWarpBuffer();
+
+    QGLWidget::closeEvent(pEvent);
+}
+
+void QProjectorWindow::initFromDOMElement(const QDomElement& element)
+{
+    bool bShowFullScreen = false;
+
+    if (!element.isNull())
+	{
+		int posX = 16;
+		int posY = 16;
+		int width = 0;
+		int height = 0;
+
+		QDomElement geom = element.firstChildElement("Geometry");
+		posX = geom.attribute("posX").toInt();
+		posY = geom.attribute("posY").toInt();
+		width = geom.attribute("width").toInt();
+		height = geom.attribute("height").toInt();
+
+		move(posX, posY);
+		if (width!=0 && height!=0)
+			resize(width, height);
+
+		bShowFullScreen = (geom.attribute("fullScreen").toLower() == "true");
+	}
+
+    if (!element.isNull() && element.attribute("show")=="true") {
+        if (bShowFullScreen)
+            showFullScreen();
+        else
+            showNormal();
+    } else
+        hide();
+}
+
+QDomElement QProjectorWindow::domElement(QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement("ProjectorWindow");
+	de.setAttribute("show", isVisible()?"true":"false");
+
+	QDomElement geom = doc.createElement("Geometry");
+	geom.setAttribute("fullScreen", isFullScreen()?"true":"false");
+	geom.setAttribute("posX", x());
+	geom.setAttribute("posY", y());
+	geom.setAttribute("width", width());
+	geom.setAttribute("height", height());
+	de.appendChild(geom);
+
+	return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QSceneViewerWindow.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QSceneViewerWindow.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QSceneViewerWindow.cpp	(revision 4)
@@ -0,0 +1,94 @@
+#include <QKeyEvent>
+#include "ProjectionModel.h"
+#include "Scene.h"
+#include "gui/QSceneViewerWindow.h"
+
+using namespace projection;
+using namespace gmtl;
+
+QSceneViewerWindow::QSceneViewerWindow(QWidget* pParent, const QGLWidget* pSharedWidget, Qt::WFlags flags) :
+    QGLViewerWidget(pParent, pSharedWidget, flags|Qt::Window)
+{
+    m_pModel = NULL;
+
+    setWindowTitle("Scene Viewer");
+    setFocusPolicy(Qt::StrongFocus);
+    resize(640, 480);
+}
+
+void QSceneViewerWindow::setModel(ProjectionModel* pModel)
+{
+    m_pModel = pModel;
+    setView(m_pModel->getScene()->getCameraCenter(), m_pModel->getScene()->getCameraRotation(), m_pModel->getScene()->getCameraDistance());
+    connect(this, SIGNAL(cameraChanged(const gmtl::Vec3f&, const gmtl::Quatf&, float)),
+            m_pModel->getScene(), SLOT(setCameraViewpoint(const gmtl::Vec3f&, const gmtl::Quatf&, float)));
+}
+
+void QSceneViewerWindow::init()
+{
+}
+
+void QSceneViewerWindow::draw()
+{
+    if (m_pModel)
+    {
+        m_pModel->setRenderContext(this);
+        m_pModel->getScene()->draw();
+
+        m_bGridVisible = m_pModel->getScene()->getShowGrid();
+        m_gridSize = m_pModel->getScene()->getGridSize();
+    }
+}
+
+void QSceneViewerWindow::resetCamera()
+{
+    setView(Vec3f(0.0f, 0.0f, 0.0f), Quatf(), 0.00001f);
+    updateGL();
+}
+
+void QSceneViewerWindow::keyReleaseEvent(QKeyEvent* pEvent)
+{
+    QGLViewerWidget::keyReleaseEvent(pEvent);
+
+    static bool bFullScreen = false;
+    switch (pEvent->key())
+    {
+    case Qt::Key_Return:
+        if (pEvent->modifiers() & Qt::AltModifier)
+        {
+            if (!bFullScreen) {
+                showFullScreen();
+                bFullScreen = true;
+            } else {
+                showNormal();
+                bFullScreen = false;
+            }
+        }
+        break;
+    default:
+        return;
+    }
+}
+
+void QSceneViewerWindow::initFromDOMElement(const QDomElement& element)
+{
+    if (element.isNull())
+        return;
+
+    QGLViewerWidget::initFromDOMElement(element);
+
+    if (element.attribute("show")=="true")
+        show();
+    else
+        hide();
+}
+
+QDomElement QSceneViewerWindow::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = QGLViewerWidget::domElement(name, doc);
+    if (isVisible())
+        de.setAttribute("show", "true");
+    else
+        de.setAttribute("show", "false");
+    return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QSceneWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QSceneWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QSceneWidget.cpp	(revision 4)
@@ -0,0 +1,114 @@
+#include "Scene.h"
+#include "ProjectionModel.h"
+#include "gui/Defines.h"
+#include "gui/QSceneWidget.h"
+
+using namespace projection;
+
+QSceneWidget::QSceneWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+
+    m_pScene = NULL;
+}
+
+QSceneWidget::~QSceneWidget()
+{
+}
+
+void QSceneWidget::setScene(Scene* pScene)
+{
+	// Note : only scene knows the scene "names". The combo and the stackedWidget have to adapt themselves to the Scene
+	Q_ASSERT(pScene);
+	Q_ASSERT(!m_pScene); // <-- If this Q_ASSERT match, this is that 'setScene()' has been called twice. Then we'll need to delete all the widgets.
+    m_pScene = pScene;
+    ui.typeComboBox->clear();
+    for (unsigned int i=0; i<m_pScene->getNumContents(); ++i)
+	{
+        QString name = m_pScene->getContentName(i);
+        ui.typeComboBox->addItem(name);
+
+		SceneContent *sc = m_pScene->getContent(name);
+		SceneInterface *si = sc->plugin();
+		SceneWidget *widget = si->newSceneWidget(sc->scene_name());
+		ui.stackedWidget->addWidget(widget);
+		widget->disconnect();
+		m_pScene->disconnect();
+		connect(widget, SIGNAL(dataChanged(const SceneContent&)), m_pScene, SLOT(updateSceneContent(const SceneContent&)));
+	}
+
+    updateGUI();
+}
+
+void QSceneWidget::updateGUI()
+{
+    if (m_pScene)
+    {
+        ui.transformWidget->setMatrix(m_pScene->getMatrix());
+
+        ui.showInDesignViewCheckBox->setChecked(m_pScene->getShowInDesignView());
+        ui.sceneSizeEdit->setText(formatValue(m_pScene->getSize()));
+        ui.gridCheckBox->setChecked(m_pScene->getShowGrid());
+        ui.gridSizeEdit->setText(formatValue(m_pScene->getShowGrid()));
+
+        ui.typeComboBox->setCurrentIndex(ui.typeComboBox->findText(m_pScene->getCurrentContentName()));
+        ui.stackedWidget->setCurrentIndex(ui.typeComboBox->currentIndex());
+
+		SceneWidget* pSceneWidget = static_cast<SceneWidget*>(ui.stackedWidget->currentWidget());
+		Q_ASSERT(NULL!=pSceneWidget);
+		pSceneWidget->updateGUI(m_pScene->getCurrentContent());
+    }
+}
+
+void QSceneWidget::on_transformWidget_matrixChanged(const TransformMatrix& matrix)
+{
+    if (m_pScene && m_pScene->getMatrix() != matrix)
+    {
+        m_pScene->setMatrix(matrix);
+        updateGUI();
+    }
+}
+
+void QSceneWidget::on_typeComboBox_activated(int)
+{
+    if (m_pScene)
+    {
+        m_pScene->setCurrentContent(ui.typeComboBox->currentText());
+        updateGUI();
+    }
+}
+
+void QSceneWidget::on_showInDesignViewCheckBox_toggled(bool checked)
+{
+    if (m_pScene)
+        m_pScene->setShowInDesignView(checked);
+}
+
+void QSceneWidget::on_sceneSizeEdit_editingFinished()
+{
+    if (m_pScene)
+        m_pScene->setSize(formatValue(ui.sceneSizeEdit->text()));
+}
+
+void QSceneWidget::on_gridCheckBox_toggled(bool checked)
+{
+    if (m_pScene)
+        m_pScene->setShowGrid(checked);
+}
+
+void QSceneWidget::on_gridSizeEdit_editingFinished()
+{
+    if (m_pScene && m_pScene->getGridSize() != ui.gridSizeEdit->text().toDouble())
+        m_pScene->setGridSize(ui.gridSizeEdit->text().toDouble());
+}
+
+void QSceneWidget::on_centerViewButton_clicked()
+{
+    m_pScene->centerView();
+}
+
+void QSceneWidget::on_viewAllButton_clicked()
+{
+    m_pScene->viewAll();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QScreenWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QScreenWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QScreenWidget.cpp	(revision 4)
@@ -0,0 +1,223 @@
+#include "Screen.h"
+#include "screen/ScreenDome.h"
+#include "screen/ScreenPlane.h"
+#include "screen/ScreenBox.h"
+#include "screen/ScreenModel.h"
+#include "gui/Defines.h"
+#include "gui/QScreenWidget.h"
+
+using namespace projection;
+
+QScreenWidget::QScreenWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+
+    m_pScreen = NULL;
+}
+
+QScreenWidget::~QScreenWidget()
+{
+}
+
+void QScreenWidget::setScreen(Screen* pScreen)
+{
+    m_pScreen = pScreen;
+    ui.typeComboBox->clear();
+    for (unsigned int i=0; i<m_pScreen->getNumShapes(); ++i)
+        ui.typeComboBox->addItem(m_pScreen->getShapeName(i));
+
+    updateGUI();
+}
+
+void QScreenWidget::updateGUI()
+{
+    if (m_pScreen)
+    {
+        ui.transformWidget->setMatrix(m_pScreen->getMatrix());
+
+        if (m_pScreen->getCurrentShapeName() == "Dome")
+        {
+            ScreenDome* pScreenDome = (ScreenDome*)m_pScreen->getCurrentShape();
+            ui.domeRadiusEdit->setText(formatValue(pScreenDome->getRadius()));
+            ui.domeAzimResSpinBox->setValue(pScreenDome->getAzimResolution());
+            ui.domeElevResSpinBox->setValue(pScreenDome->getElevResolution());
+            ui.domeSubdivSpinBox->setValue(pScreenDome->getSubdivision());
+            ui.domeFullDomeCheckBox->setChecked(pScreenDome->getFullDome());
+        }
+        else if (m_pScreen->getCurrentShapeName() == "Plane")
+        {
+            ScreenPlane* pScreenPlane = (ScreenPlane*)m_pScreen->getCurrentShape();
+            ui.planeWidthEdit->setText(formatValue(pScreenPlane->getWidth()));
+            ui.planeHeightEdit->setText(formatValue(pScreenPlane->getHeight()));
+            ui.planeHorResSpinBox->setValue(pScreenPlane->getHorResolution());
+            ui.planeVertResSpinBox->setValue(pScreenPlane->getVertResolution());
+        }
+        else if (m_pScreen->getCurrentShapeName() == "Box")
+        {
+            ScreenBox* pScreenBox = (ScreenBox*)m_pScreen->getCurrentShape();
+            ui.boxWidthEdit->setText(formatValue(pScreenBox->getWidth()));
+            ui.boxHeightEdit->setText(formatValue(pScreenBox->getHeight()));
+            ui.boxDepthEdit->setText(formatValue(pScreenBox->getDepth()));
+            ui.boxHorResSpinBox->setValue(pScreenBox->getHorResolution());
+            ui.boxVertResSpinBox->setValue(pScreenBox->getVertResolution());
+            ui.boxDepthResSpinBox->setValue(pScreenBox->getDepthResolution());
+        }
+        else if (m_pScreen->getCurrentShapeName() == "Model")
+        {
+            ScreenModel* pScreenModel = (ScreenModel*)m_pScreen->getCurrentShape();
+            ui.modelFileNameEdit->setText(pScreenModel->getFileName());
+        }
+        ui.frameCheckBox->setChecked(m_pScreen->getShowFrame());
+        ui.frameLineWidthSpinBox->setValue(m_pScreen->getFrameLineWidth());
+
+        ui.typeComboBox->setCurrentIndex(ui.typeComboBox->findText(m_pScreen->getCurrentShapeName()));
+        ui.stackedWidget->setCurrentIndex(ui.typeComboBox->currentIndex());
+    }
+}
+
+void QScreenWidget::on_typeComboBox_activated(int)
+{
+    if (m_pScreen)
+    {
+        m_pScreen->setCurrentShape(ui.typeComboBox->currentText());
+        updateGUI();
+    }
+}
+
+void QScreenWidget::on_transformWidget_matrixChanged(const TransformMatrix& matrix)
+{
+    if (m_pScreen && m_pScreen->getMatrix() != matrix)
+    {
+        m_pScreen->setMatrix(matrix);
+        updateGUI();
+    }
+}
+
+void QScreenWidget::on_domeRadiusEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Dome")
+        ((ScreenDome*)m_pScreen->getCurrentShape())->setRadius(ui.domeRadiusEdit->text().toDouble());
+}
+
+void QScreenWidget::on_domeAzimResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Dome")
+        ((ScreenDome*)m_pScreen->getCurrentShape())->setAzimResolution(value);
+}
+
+void QScreenWidget::on_domeElevResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Dome")
+        ((ScreenDome*)m_pScreen->getCurrentShape())->setElevResolution(value);
+}
+
+void QScreenWidget::on_domeSubdivSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Dome")
+        ((ScreenDome*)m_pScreen->getCurrentShape())->setSubdivision(value);
+}
+
+void QScreenWidget::on_domeFullDomeCheckBox_toggled(bool checked)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Dome")
+        ((ScreenDome*)m_pScreen->getCurrentShape())->setFullDome(checked);
+}
+
+void QScreenWidget::on_planeWidthEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Plane")
+        ((ScreenPlane*)m_pScreen->getCurrentShape())->setWidth(ui.planeWidthEdit->text().toDouble());
+}
+
+void QScreenWidget::on_planeHeightEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Plane")
+        ((ScreenPlane*)m_pScreen->getCurrentShape())->setHeight(ui.planeHeightEdit->text().toDouble());
+}
+
+void QScreenWidget::on_planeHorResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Plane")
+        ((ScreenPlane*)m_pScreen->getCurrentShape())->setHorResolution(value);
+}
+
+void QScreenWidget::on_planeVertResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Plane")
+        ((ScreenPlane*)m_pScreen->getCurrentShape())->setVertResolution(value);
+}
+
+void QScreenWidget::on_boxWidthEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setWidth(ui.boxWidthEdit->text().toDouble());
+}
+
+void QScreenWidget::on_boxHeightEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setHeight(ui.boxHeightEdit->text().toDouble());
+}
+
+void QScreenWidget::on_boxDepthEdit_editingFinished()
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setDepth(ui.boxDepthEdit->text().toDouble());
+}
+
+void QScreenWidget::on_boxHorResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setHorResolution(value);
+}
+
+void QScreenWidget::on_boxVertResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setVertResolution(value);
+}
+
+void QScreenWidget::on_boxDepthResSpinBox_valueChanged(int value)
+{
+    if (m_pScreen && m_pScreen->getCurrentShapeName() == "Box")
+        ((ScreenBox*)m_pScreen->getCurrentShape())->setDepthResolution(value);
+}
+
+void QScreenWidget::on_modelFileNameEdit_editingFinished()
+{
+	if (m_pScreen && m_pScreen->getCurrentShapeName() == "Model" && ui.modelFileNameEdit->text() != "" )
+	{
+		if (QFile::exists(ui.modelFileNameEdit->text()))
+		{
+			((ScreenModel*)m_pScreen->getCurrentShape())->setFileName(ui.modelFileNameEdit->text());
+			//QMessageBox::information(this,"moep!",".");
+		}
+		else
+		{
+			QMessageBox::warning(this,"Filename not Found!","Filename not Found!<br><br>Your selection will be cleared.");
+			ui.modelFileNameEdit->clear();
+		}
+	}
+}
+
+void QScreenWidget::on_modelBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, "Choose a file to open", ui.modelFileNameEdit->text(), "Model files (*.obj)");
+    if (!fileName.isEmpty()) {
+        ui.modelFileNameEdit->setText(fileName);
+        on_modelFileNameEdit_editingFinished();
+    }
+}
+
+void QScreenWidget::on_frameCheckBox_toggled(bool checked)
+{
+    if (m_pScreen)
+        m_pScreen->setShowFrame(checked);
+}
+
+void QScreenWidget::on_frameLineWidthSpinBox_valueChanged(int value)
+{
+    if (m_pScreen)
+        m_pScreen->setFrameLineWidth(value);
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/QTransformMatrixWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/QTransformMatrixWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/QTransformMatrixWidget.cpp	(revision 4)
@@ -0,0 +1,138 @@
+#include "gui/Defines.h"
+#include "gui/QTransformMatrixWidget.h"
+
+using namespace projection;
+using namespace gmtl;
+
+QTransformMatrixWidget::QTransformMatrixWidget(QWidget* pParent, Qt::WFlags flags)
+    : QWidget(pParent, flags)
+{
+    ui.setupUi(this);
+    m_bStopSlot = false;
+}
+
+QTransformMatrixWidget::~QTransformMatrixWidget()
+{
+}
+
+void QTransformMatrixWidget::setMatrix(const TransformMatrix& matrix)
+{
+    if (m_bStopSlot) return;
+
+    Vec3f pos = matrix.getPosition();
+    Vec3f rot = matrix.getRotation();
+    Vec3f scale = matrix.getScaling();
+    ui.posXEdit->setText(formatValue(pos[0]));
+    ui.posYEdit->setText(formatValue(pos[1]));
+    ui.posZEdit->setText(formatValue(pos[2]));
+    ui.rotHEdit->setText(formatValue(rot[0]));
+    ui.rotPEdit->setText(formatValue(rot[1]));
+    ui.rotREdit->setText(formatValue(rot[2]));
+    ui.scaleXEdit->setText(formatValue(scale[0]));
+    ui.scaleYEdit->setText(formatValue(scale[1]));
+    ui.scaleZEdit->setText(formatValue(scale[2]));
+
+//    checkValueChanged();
+    m_matrix = matrix;
+}
+
+TransformMatrix QTransformMatrixWidget::getMatrix() const
+{
+    return m_matrix;
+}
+
+void QTransformMatrixWidget::clear()
+{
+    ui.posXEdit->setText("");
+    ui.posYEdit->setText("");
+    ui.posZEdit->setText("");
+    ui.rotHEdit->setText("");
+    ui.rotPEdit->setText("");
+    ui.rotREdit->setText("");
+    ui.scaleXEdit->setText("");
+    ui.scaleYEdit->setText("");
+    ui.scaleZEdit->setText("");
+    m_matrix = TransformMatrix();
+}
+
+void QTransformMatrixWidget::setUseScale(bool bUseScale)
+{
+    if (bUseScale)
+    {
+        ui.scaleLabel->show();
+        ui.scaleXEdit->show();
+        ui.scaleYEdit->show();
+        ui.scaleZEdit->show();
+    }
+    else
+    {
+        ui.scaleLabel->hide();
+        ui.scaleXEdit->hide();
+        ui.scaleYEdit->hide();
+        ui.scaleZEdit->hide();
+    }
+}
+
+void QTransformMatrixWidget::checkValueChanged()
+{
+    Vec3f pos(ui.posXEdit->text().toFloat(), ui.posYEdit->text().toFloat(), ui.posZEdit->text().toFloat());
+    Vec3f rot(ui.rotHEdit->text().toFloat(), ui.rotPEdit->text().toFloat(), ui.rotREdit->text().toFloat());
+    Vec3f scale(ui.scaleXEdit->text().toFloat(), ui.scaleYEdit->text().toFloat(), ui.scaleZEdit->text().toFloat());
+    TransformMatrix matrix;
+    matrix.setPosition(pos);
+    matrix.setRotation(rot);
+    matrix.setScaling(scale);
+
+    if (m_matrix != matrix)
+    {
+        m_matrix = matrix;
+        m_bStopSlot = true;
+        emit matrixChanged(m_matrix);
+        m_bStopSlot = false;
+    }
+}
+
+void QTransformMatrixWidget::on_posXEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_posYEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_posZEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_rotHEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_rotPEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_rotREdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_scaleXEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_scaleYEdit_editingFinished()
+{
+    checkValueChanged();
+}
+
+void QTransformMatrixWidget::on_scaleZEdit_editingFinished()
+{
+    checkValueChanged();
+}
Index: projectionDesigner/trunk/projdesigner/src/gui/plugindialog.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/gui/plugindialog.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/gui/plugindialog.cpp	(revision 4)
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
+**
+** This file is part of the example classes of the Qt Toolkit.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "interfaces.h"
+#include "plugindialog.h"
+
+PluginDialog::PluginDialog(const QString &path, const QStringList &fileNames,
+                           QWidget *parent)
+    : QDialog(parent)
+{
+    label = new QLabel;
+
+    treeWidget = new QTreeWidget;
+    treeWidget->setAlternatingRowColors(false);
+    treeWidget->setSelectionMode(QAbstractItemView::NoSelection);
+    treeWidget->setColumnCount(1);
+    treeWidget->header()->hide();
+
+    okButton = new QPushButton(tr("OK"));
+    okButton->setDefault(true);
+
+    connect(okButton, SIGNAL(clicked()), this, SLOT(close()));
+
+    QGridLayout *mainLayout = new QGridLayout;
+    mainLayout->setColumnStretch(0, 1);
+    mainLayout->setColumnStretch(2, 1);
+    mainLayout->addWidget(label, 0, 0, 1, 3);
+    mainLayout->addWidget(treeWidget, 1, 0, 1, 3);
+    mainLayout->addWidget(okButton, 2, 1);
+    setLayout(mainLayout);
+
+    interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
+                            QIcon::Normal, QIcon::On);
+    interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
+                            QIcon::Normal, QIcon::Off);
+    featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
+
+    setWindowTitle(tr("Plugin Information"));
+    findPlugins(path, fileNames);
+}
+
+void PluginDialog::findPlugins(const QString &path,
+                               const QStringList &fileNames)
+{
+    label->setText(tr("ProjDesigner found the following plugins\n"
+                      "(looked in %1):")
+                   .arg(QDir::toNativeSeparators(path)));
+
+    QDir dir(path);
+
+    foreach (QObject *plugin, QPluginLoader::staticInstances())
+        populateTreeWidget(plugin, tr("%1 (Static Plugin)")
+													 .arg(plugin->metaObject()->className()));
+
+    foreach (QString fileName, fileNames) {
+        QPluginLoader loader(dir.absoluteFilePath(fileName));
+        QObject *plugin = loader.instance();
+        if (plugin)
+            populateTreeWidget(plugin, fileName);
+    }
+}
+
+void PluginDialog::populateTreeWidget(QObject *plugin, const QString &text)
+{
+    QTreeWidgetItem *pluginItem = new QTreeWidgetItem(treeWidget);
+    pluginItem->setText(0, text);
+    treeWidget->setItemExpanded(pluginItem, true);
+
+    QFont boldFont = pluginItem->font(0);
+    boldFont.setBold(true);
+    pluginItem->setFont(0, boldFont);
+
+    if (plugin) {
+        ProjectorInterface *projector_plugin =
+                qobject_cast<ProjectorInterface*>(plugin);
+        if (projector_plugin)
+						addItems(pluginItem, "ProjectorInterface", projector_plugin->projectors());
+        SceneInterface *scene_plugin =
+                qobject_cast<SceneInterface*>(plugin);
+        if (scene_plugin)
+						addItems(pluginItem, "SceneInterface", scene_plugin->scenes());
+    }
+}
+
+void PluginDialog::addItems(QTreeWidgetItem *pluginItem,
+                            const char *interfaceName,
+                            const QStringList &features)
+{
+    QTreeWidgetItem *interfaceItem = new QTreeWidgetItem(pluginItem);
+    interfaceItem->setText(0, interfaceName);
+    interfaceItem->setIcon(0, interfaceIcon);
+
+    foreach (QString feature, features) {
+        if (feature.endsWith("..."))
+            feature.chop(3);
+        QTreeWidgetItem *featureItem = new QTreeWidgetItem(interfaceItem);
+        featureItem->setText(0, feature);
+        featureItem->setIcon(0, featureIcon);
+    }
+}
Index: projectionDesigner/trunk/projdesigner/src/math/ProjectionMatrix.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/math/ProjectionMatrix.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/math/ProjectionMatrix.cpp	(revision 4)
@@ -0,0 +1,148 @@
+#include "math/ProjectionMatrix.h"
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor.
+ *
+ * Default projection matrix value is : FOV=30.0, 
+ * AspectRatio=4/3, Near=0.1, Far=100.0
+ */
+ProjectionMatrix::ProjectionMatrix()
+{
+    m_fov = 30.0f;
+    m_aspectRatio = 1024.0f / 768.0f;
+    m_near = 0.1f;
+    m_far = 100.0f;
+    m_offaxisX = 0.0f;
+    m_offaxisY = 0.0f;
+}
+
+/**
+ * Destructor.
+ */
+ProjectionMatrix::~ProjectionMatrix()
+{
+}
+
+/**
+ * Copy constructor.
+ *
+ * @param matrix Copy source matrix.
+ */
+ProjectionMatrix::ProjectionMatrix(const ProjectionMatrix &matrix)
+{
+    m_fov = matrix.getFOV();
+    m_aspectRatio = matrix.getAspectRatio();
+    m_near = matrix.getNear();
+    m_far = matrix.getFar();
+    m_offaxisX = matrix.getOffaxisX();
+    m_offaxisY = matrix.getOffaxisY();
+}
+
+/**
+ * Retrieve matrix values for glMultMatrixd().
+ *
+ * @return Matrix values.
+ */
+float* ProjectionMatrix::getMatrix()
+{
+    // glMultMatrixd(getMatrix()) is same as glFrustum().
+    float left =   (-tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) - m_offaxisX) * m_near;
+    float right =  ( tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) - m_offaxisX) * m_near;
+    float top =    ( tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY) * m_near;
+    float bottom = (-tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY) * m_near;
+    m_mat[ 0] = (2.0f * m_near) / (right - left);
+    m_mat[ 1] = 0.0f;
+    m_mat[ 2] = 0.0f;
+    m_mat[ 3] = 0.0f;
+    m_mat[ 4] = 0.0f;
+    m_mat[ 5] = (2.0f * m_near) / (top - bottom);
+    m_mat[ 6] = 0.0f;
+    m_mat[ 7] = 0.0f;
+    m_mat[ 8] = (right + left) / (right - left);
+    m_mat[ 9] = (top + bottom) / (top - bottom);
+    m_mat[10] = -(m_far + m_near) / (m_far - m_near);
+    m_mat[11] = -1.0f;
+    m_mat[12] = 0.0f;
+    m_mat[13] = 0.0f;
+    m_mat[14] = -(2.0f * m_far * m_near) / (m_far - m_near);
+    m_mat[15] = 0.0f;
+
+    return m_mat;
+}
+
+/**
+ * Retrieve four corner vectors.
+ *
+ * @param Four corner vectors.
+ */
+void ProjectionMatrix::getCorners(gmtl::Vec3f vecs[4]) const
+{
+    float left =   (-tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) + m_offaxisX);
+    float right =  ( tanf(Math::deg2Rad(m_fov) / 2.0f * m_aspectRatio) + m_offaxisX);
+    float top =    ( tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY);
+    float bottom = (-tanf(Math::deg2Rad(m_fov) / 2.0f) + m_offaxisY);
+    vecs[0].set(left, 1.0f, top);
+    vecs[1].set(right, 1.0f, top);
+    vecs[2].set(right, 1.0f, bottom);
+    vecs[3].set(left, 1.0f, bottom);
+    normalize(vecs[0]);
+    normalize(vecs[1]);
+    normalize(vecs[2]);
+    normalize(vecs[3]);
+}
+
+/**
+ * Retrieve frustum parameters as 'Frustum left right bottom top near far;'.
+ *
+ * @param numSpaces Number of space characters for indent.
+ * @return Frustum params.
+ */
+QString ProjectionMatrix::getParams(int numSpaces) const
+{
+    QString spc;
+    spc.fill(' ', numSpaces);
+    double left =   (-tan(Math::deg2Rad(m_fov) / 2.0 * m_aspectRatio) + m_offaxisX);
+    double right =  ( tan(Math::deg2Rad(m_fov) / 2.0 * m_aspectRatio) + m_offaxisX);
+    double top =    ( tan(Math::deg2Rad(m_fov) / 2.0) + m_offaxisY);
+    double bottom = (-tan(Math::deg2Rad(m_fov) / 2.0) + m_offaxisY);
+  return spc + QString("Frustum %1 %2 %3 %4 %5 %6;").arg(left*m_near).arg(right*m_near).arg(bottom*m_near).arg(top*m_near).arg(m_near).arg(m_far);
+}
+
+/**
+ * Restore the projection matrix from XML data.
+ *
+ * @param element Parent XML element of the projection matrix data.
+ */
+void ProjectionMatrix::initFromDOMElement(const QDomElement& element)
+{
+	m_fov = element.attribute("fov").toFloat();
+	m_aspectRatio = element.attribute("aspectRatio").toFloat();
+	m_near = element.attribute("near").toFloat();
+	m_far = element.attribute("far").toFloat();
+	m_offaxisX = element.attribute("offaxisX").toFloat();
+	m_offaxisY = element.attribute("offaxisY").toFloat();
+}
+
+/**
+ * Store the current projection matrix as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen shape data as XML data.
+ */
+QDomElement ProjectionMatrix::domElement(const QString& name, QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement(name);
+
+	de.setAttribute("fov", QString::number(m_fov));
+	de.setAttribute("aspectRatio", QString::number(m_aspectRatio));
+	de.setAttribute("near", QString::number(m_near));
+	de.setAttribute("far", QString::number(m_far));
+	de.setAttribute("offaxisX", QString::number(m_offaxisX));
+	de.setAttribute("offaxisY", QString::number(m_offaxisY));
+
+	return de;
+}
Index: projectionDesigner/trunk/projdesigner/src/math/TransformMatrix.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/math/TransformMatrix.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/math/TransformMatrix.cpp	(revision 4)
@@ -0,0 +1,143 @@
+#include "math/TransformMatrix.h"
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor.
+ *
+ * Default transform matrix value is identity matrix.
+ */
+TransformMatrix::TransformMatrix()
+{
+		reset ();
+}
+
+/**
+ * Destructor.
+ */
+TransformMatrix::~TransformMatrix()
+{
+}
+
+/**
+ * Retrieve the trasform matrix.
+ *
+ * @return Trasform matrix.
+ */
+gmtl::Matrix44f TransformMatrix::getMatrix() const
+{
+    return makeTrans<Matrix44f>(m_pos) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[0]), Vec3f(0.0f, 1.0f, 0.0f))) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[1]), Vec3f(1.0f, 0.0f, 0.0f))) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[2]), Vec3f(0.0f, 0.0f, 1.0f))) *
+        makeScale<Matrix44f>(m_scale);
+}
+
+/**
+ * Retrieve the trasform matrix without scaling.
+ *
+ * @return Trasform matrix without scaling.
+ */
+gmtl::Matrix44f TransformMatrix::getMatrixWOScaling() const
+{
+    return makeTrans<Matrix44f>(m_pos) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[0]), Vec3f(0.0f, 1.0f, 0.0f))) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[1]), Vec3f(1.0f, 0.0f, 0.0f))) *
+        makeRot<Matrix44f>(AxisAnglef(Math::deg2Rad(m_rot[2]), Vec3f(0.0f, 0.0f, 1.0f)));
+}
+
+/**
+ * Retrieve transform parameters like 'Rotate 45 1 0 0;'.
+ *
+ * @param numSpaces Number of space characters for indent.
+ * @return Transform params.
+ */
+QString TransformMatrix::getParams(int space) const
+{
+    QString spc;
+    spc.fill(' ', space);
+
+    QString result;
+    if (m_scale != Vec3f(1.0f, 1.0f, 1.0f))
+        result += spc + QString("Scale %1 %2 %3;\n").arg(m_scale[0]).arg(m_scale[1]).arg(m_scale[2]);
+    if (m_rot[2] != 0.0)
+        result += spc + QString("Rotate %1 0 0 1;\n").arg(m_rot[2]);
+    if (m_rot[1] != 0.0)
+        result += spc + QString("Rotate %1 1 0 0;\n").arg(m_rot[1]);
+    if (m_rot[0] != 0.0)
+        result += spc + QString("Rotate %1 0 1 0;\n").arg(m_rot[0]);
+    if (m_pos != Vec3f(0.0f, 0.0f, 0.0f))
+        result += spc + QString("Translate %1 %2 %3;\n").arg(m_pos[0]).arg(m_pos[1]).arg(m_pos[2]);
+
+    return result;
+}
+
+/**
+ * Restore the transform matrix from XML data.
+ *
+ * @param element Parent XML element of the transform matrix data.
+ */
+void TransformMatrix::initFromDOMElement(const QDomElement& element)
+{
+    QDomElement pos = element.firstChildElement("position");
+    m_pos[0] = pos.attribute("x").toFloat();
+    m_pos[1] = pos.attribute("y").toFloat();
+    m_pos[2] = pos.attribute("z").toFloat();
+
+    QDomElement rot = element.firstChildElement("rotation");
+    m_rot[0] = rot.attribute("h").toFloat();
+    m_rot[1] = rot.attribute("p").toFloat();
+    m_rot[2] = rot.attribute("r").toFloat();
+
+    if (!element.firstChildElement("scaling").isNull())
+    {
+        QDomElement scale = element.firstChildElement("scaling");
+        m_scale[0] = scale.attribute("x").toFloat();
+        m_scale[1] = scale.attribute("y").toFloat();
+        m_scale[2] = scale.attribute("z").toFloat();
+    }
+}
+
+/**
+ * Store the current transform matrix as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current transform matrix data as XML data.
+ */
+QDomElement TransformMatrix::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+
+    QDomElement pos = doc.createElement("position");
+    pos.setAttribute("x", QString::number(m_pos[0]));
+    pos.setAttribute("y", QString::number(m_pos[1]));
+    pos.setAttribute("z", QString::number(m_pos[2]));
+    de.appendChild(pos);
+
+    QDomElement rot = doc.createElement("rotation");
+    rot.setAttribute("h", QString::number(m_rot[0]));
+    rot.setAttribute("p", QString::number(m_rot[1]));
+    rot.setAttribute("r", QString::number(m_rot[2]));
+    de.appendChild(rot);
+
+    QDomElement scale = doc.createElement("scaling");
+    scale.setAttribute("x", QString::number(m_scale[0]));
+    scale.setAttribute("y", QString::number(m_scale[1]));
+    scale.setAttribute("z", QString::number(m_scale[2]));
+    de.appendChild(scale);
+
+    return de;
+}
+
+/**
+ * Reset the matrix.
+ */
+void TransformMatrix::reset()
+{
+    m_pos.set(0.0f, 0.0f, 0.0f);
+    m_rot.set(0.0f, 0.0f, 0.0f);
+    m_scale.set(1.0f, 1.0f, 1.0f);
+    m_bUseScale = true;
+}
Index: projectionDesigner/trunk/projdesigner/src/screen/ScreenBox.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/screen/ScreenBox.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/screen/ScreenBox.cpp	(revision 4)
@@ -0,0 +1,273 @@
+#include "screen/ScreenBox.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pScreen Screen data.
+ */
+ScreenBox::ScreenBox(Screen* pScreen) : ScreenShape(pScreen)
+{
+    m_width = 2.0;
+    m_height = 2.0;
+    m_depth = 2.0;
+    m_horResolution = 4;
+    m_vertResolution = 4;
+    m_depthResolution = 4;
+}
+
+/**
+ * Destructor.
+ */
+ScreenBox::~ScreenBox()
+{
+}
+
+/**
+ * Set width of the box screen.
+ *
+ * @param width Width of the box screen.
+ */
+void ScreenBox::setWidth(double width)
+{
+    if (m_width != width)
+    {
+        m_width = width;
+	    notifyRedraw();
+    }
+}
+
+/**
+ * Set height of the box screen.
+ *
+ * @param height Height of the box screen.
+ */
+void ScreenBox::setHeight(double height)
+{
+    if (m_height != height)
+    {
+        m_height = height;
+	    notifyRedraw();
+    }
+}
+
+/**
+ * Set depth of the box screen.
+ *
+ * @param depth Depth of the box screen.
+ */
+void ScreenBox::setDepth(double depth)
+{
+    if (m_depth != depth)
+    {
+        m_depth = depth;
+	    notifyRedraw();
+    }
+}
+
+/**
+ * Set horizontal resolution of the box screen.
+ *
+ * @param resolution Horizontal resolution of the box screen.
+ */
+void ScreenBox::setHorResolution(unsigned int resolution)
+{
+    m_horResolution = resolution;
+	notifyRedraw();
+}
+
+/**
+ * Set vertical resolution of the box screen.
+ *
+ * @param resolution Vertical resolution of the box screen.
+ */
+void ScreenBox::setVertResolution(unsigned int resolution)
+{
+    m_vertResolution = resolution;
+	notifyRedraw();
+}
+
+/**
+ * Set depth resolution of the box screen.
+ *
+ * @param resolution Depth resolution of the box screen.
+ */
+void ScreenBox::setDepthResolution(unsigned int resolution)
+{
+    m_depthResolution = resolution;
+	notifyRedraw();
+}
+
+/**
+ * Retrieve bounding box of the screen shape.
+ *
+ * @param min One corner of the screen shape.
+ * @param max Another corner of the screen shape.
+ */
+void ScreenBox::getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max)
+{
+	min.set((float)-m_width/2.0f, (float)-m_depth/2.0f, (float)-m_height/2.0f);
+	max.set((float)m_width/2.0f, (float)m_depth/2.0f, (float)m_height/2.0f);
+}
+
+/**
+ * Restore the screen shape from XML data.
+ *
+ * @param element Parent XML element of the screen shape data.
+ */
+bool ScreenBox::initFromDOMElement(const QDomElement& element)
+{
+    // don't notify redrawing by each restoring step
+	if (!element.isNull())
+	{
+		m_width = element.attribute("width").toFloat();
+		m_height = element.attribute("height").toFloat();
+		m_depth = element.attribute("depth").toFloat();
+		m_horResolution = element.attribute("horResolution").toInt();
+		m_vertResolution = element.attribute("vertResolution").toInt();
+		m_depthResolution = element.attribute("depthResolution").toInt();
+        // if change
+        notifyRedraw();
+	}
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current screen shape as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen shape data as XML data.
+ */
+QDomElement ScreenBox::domElement(const QString& name, QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement(name);
+	de.setAttribute("name", getName());
+	de.setAttribute("width", m_width);
+	de.setAttribute("height", m_height);
+	de.setAttribute("depth", m_depth);
+	de.setAttribute("horResolution", m_horResolution);
+	de.setAttribute("vertResolution", m_vertResolution);
+	de.setAttribute("depthResolution", m_depthResolution);
+
+	return de;
+}
+
+/**
+ * Draw the shape model in inherited class.
+ *
+ * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+ */
+void ScreenBox::drawShape(bool)
+{
+	glPushAttrib(GL_ENABLE_BIT);
+	glEnable(GL_CULL_FACE);
+
+	double horDelta = m_width / m_horResolution;
+    double vertDelta = m_height / m_vertResolution;
+    double depthDelta = m_depth / m_depthResolution;
+	unsigned int horCount;
+	unsigned int vertCount;
+	unsigned int depthCount;
+
+    for (vertCount=0; vertCount<m_vertResolution; ++vertCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (horCount=0; horCount<=m_horResolution; ++horCount)
+        {
+            glNormal3d(0, 1, 0);
+            glVertex3d(-m_width/2.0 + horDelta*horCount,
+					   -m_depth/2.0,
+                       -m_height/2.0 + vertDelta*vertCount);
+            glNormal3d(0, 1, 0);
+            glVertex3d(-m_width/2.0 + horDelta*(horCount),
+					   -m_depth/2.0,
+                       -m_height/2.0 + vertDelta*(vertCount+1));
+        }
+        glEnd();
+    }
+    for (vertCount=0; vertCount<m_vertResolution; ++vertCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (horCount=0; horCount<=m_horResolution; ++horCount)
+        {
+            glNormal3d(0, -1, 0);
+            glVertex3d(m_width/2.0 - horDelta*horCount,
+					   m_depth/2.0,
+                       -m_height/2.0 + vertDelta*vertCount);
+            glNormal3d(0, -1, 0);
+            glVertex3d(m_width/2.0 - horDelta*(horCount),
+					   m_depth/2.0,
+                       -m_height/2.0 + vertDelta*(vertCount+1));
+        }
+        glEnd();
+    }
+    for (vertCount=0; vertCount<m_vertResolution; ++vertCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (depthCount=0; depthCount<=m_depthResolution; ++depthCount)
+        {
+            glNormal3d(1, 0, 0);
+            glVertex3d(-m_width/2.0,
+					   m_depth/2.0 - depthDelta*depthCount,
+                       -m_height/2.0 + vertDelta*vertCount);
+            glNormal3d(1, 0, 0);
+            glVertex3d(-m_width/2.0,
+					   m_depth/2.0 - depthDelta*(depthCount),
+                       -m_height/2.0 + vertDelta*(vertCount+1));
+        }
+        glEnd();
+    }
+    for (vertCount=0; vertCount<m_vertResolution; ++vertCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (depthCount=0; depthCount<=m_depthResolution; ++depthCount)
+        {
+            glNormal3d(-1, 0, 0);
+            glVertex3d(m_width/2.0,
+					   -m_depth/2.0 + depthDelta*depthCount,
+                       -m_height/2.0 + vertDelta*vertCount);
+            glNormal3d(-1, 0, 0);
+            glVertex3d(m_width/2.0,
+					   -m_depth/2.0 + depthDelta*(depthCount),
+                       -m_height/2.0 + vertDelta*(vertCount+1));
+        }
+        glEnd();
+    }
+    for (depthCount=0; depthCount<m_depthResolution; ++depthCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (horCount=0; horCount<=m_horResolution; ++horCount)
+        {
+            glNormal3d(0, 0, 1);
+            glVertex3d(m_width/2.0 - horDelta*horCount,
+					   -m_depth/2.0 + depthDelta*depthCount,
+                       -m_height/2.0);
+            glNormal3d(0, 0, 1);
+            glVertex3d(m_width/2.0 - horDelta*horCount,
+					   -m_depth/2.0 + depthDelta*(depthCount+1),
+                       -m_height/2.0);
+        }
+        glEnd();
+    }
+    for (depthCount=0; depthCount<m_depthResolution; ++depthCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (horCount=0; horCount<=m_horResolution; ++horCount)
+        {
+            glNormal3d(0, 0, -1);
+            glVertex3d(-m_width/2.0 + horDelta*horCount,
+					   -m_depth/2.0 + depthDelta*depthCount,
+                       m_height/2.0);
+            glNormal3d(0, 0, -1);
+            glVertex3d(-m_width/2.0 + horDelta*horCount,
+					   -m_depth/2.0 + depthDelta*(depthCount+1),
+                       m_height/2.0);
+        }
+        glEnd();
+    }
+
+	glPopAttrib();
+}
Index: projectionDesigner/trunk/projdesigner/src/screen/ScreenDome.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/screen/ScreenDome.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/screen/ScreenDome.cpp	(revision 4)
@@ -0,0 +1,221 @@
+#include "screen/ScreenDome.h"
+
+using namespace projection;
+using namespace gmtl;
+
+/**
+ * Constructor.
+ *
+ * @param pScreen Screen data.
+ */
+ScreenDome::ScreenDome(Screen* pScreen) : ScreenShape(pScreen)
+{
+    m_radius = 1.0;
+    m_elevResolution = 16;
+    m_azimResolution = 16;
+    m_subdiv = 4;
+    m_bFullDome = false;
+}
+
+/**
+ * Destructor.
+ */
+ScreenDome::~ScreenDome()
+{
+}
+
+/**
+ * Set radius of the dome screen.
+ *
+ * @param radius Radius of the dome screen.
+ */
+void ScreenDome::setRadius(double radius)
+{
+    if (m_radius != radius)
+    {
+	    m_radius = radius;
+	    notifyRedraw();
+    }
+}
+
+/**
+ * Set elevation resolution of the dome screen.
+ *
+ * @param resolution Elevation resolution of the dome screen.
+ */
+void ScreenDome::setElevResolution(unsigned int resolution)
+{
+	m_elevResolution = resolution;
+	notifyRedraw();
+}
+
+/**
+ * Set azimuth resolution of the dome screen.
+ *
+ * @param resolution Azimuth resolution of the dome screen.
+ */
+void ScreenDome::setAzimResolution(unsigned int resolution)
+{
+	m_azimResolution = resolution;
+	notifyRedraw();
+}
+
+/**
+ * Retrieve azimuth resolution of the dome screen.
+ *
+ * @return Azimuth resolution of the dome screen.
+ */
+void ScreenDome::setSubdivision(unsigned int subdiv)
+{
+	m_subdiv = subdiv;
+	notifyRedraw();
+}
+
+/**
+ * Select full dome or half dome.
+ *
+ * @param bFullDome True to select a full dome, False to select a half dome.
+ */
+void ScreenDome::setFullDome(bool bFullDome)
+{
+    m_bFullDome = bFullDome;
+	notifyRedraw();
+}
+
+/**
+ * Retrieve bounding box of the screen shape.
+ *
+ * @param min One corner of the screen shape.
+ * @param max Another corner of the screen shape.
+ */
+void ScreenDome::getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max)
+{
+	min.set(-m_radius, -m_radius, 0.0);
+	max.set(m_radius, m_radius, m_radius);
+}
+
+/**
+ * Restore the screen shape from XML data.
+ *
+ * @param element Parent XML element of the screen shape data.
+ */
+bool ScreenDome::initFromDOMElement(const QDomElement& element)
+{
+    // don't notify redrawing by each restoring step
+	if (!element.isNull())
+	{
+		m_radius = element.attribute("radius").toFloat();
+		m_elevResolution = element.attribute("elevResolution").toInt();
+		m_azimResolution = element.attribute("azimResolution").toInt();
+		m_subdiv = element.attribute("subdivision").toInt();
+		m_bFullDome= element.attribute("fullDome")=="true";
+        // if change
+        notifyRedraw();
+	}
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current screen shape as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen shape data as XML data.
+ */
+QDomElement ScreenDome::domElement(const QString& name, QDomDocument& doc) const
+{
+	QDomElement de = doc.createElement(name);
+	de.setAttribute("name", getName());
+	de.setAttribute("radius", m_radius);
+	de.setAttribute("elevResolution", m_elevResolution);
+	de.setAttribute("azimResolution", m_azimResolution);
+	de.setAttribute("subdivision", m_subdiv);
+    de.setAttribute("fullDome", m_bFullDome?"true":"false");
+
+	return de;
+}
+
+/**
+ * Draw the shape model in inherited class.
+ *
+ * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+ */
+void ScreenDome::drawShape(bool bFrame)
+{
+    if (!bFrame)
+    {
+        // draw as a polygon model
+        double azimDelta = Math::PI / m_azimResolution / m_subdiv;
+	    double elevDelta = Math::PI / 2.0 / m_elevResolution / m_subdiv;
+        if (m_bFullDome) azimDelta *= 2.0;
+        for (unsigned int elevCount=0; elevCount<m_elevResolution*m_subdiv; ++elevCount)
+	    {
+		    glBegin(GL_QUAD_STRIP);
+            for (unsigned int azimCount=0; azimCount<=m_azimResolution*m_subdiv; ++azimCount)
+		    {
+			    double nx, ny, nz;
+			    nx = cos(-azimDelta*azimCount) * cos(elevDelta*elevCount);
+			    ny = sin(elevDelta*elevCount);
+			    nz = sin(-azimDelta*azimCount) * cos(elevDelta*elevCount);
+			    glNormal3d(-nx, -ny, -nz);
+			    glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+			    nx = cos(-azimDelta*azimCount) * cos(elevDelta*(elevCount+1));
+			    ny = sin(elevDelta*(elevCount+1));
+			    nz = sin(-azimDelta*azimCount) * cos(elevDelta*(elevCount+1));
+			    glNormal3d(-nx, -ny, -nz);
+			    glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+		    }
+		    glEnd();
+        }
+    }
+    else
+    {
+        // draw as a wire frame model
+
+        double azimDelta = Math::PI / m_azimResolution / m_subdiv;
+	    double elevDelta = Math::PI / 2.0 / m_elevResolution / m_subdiv;
+        if (m_bFullDome) azimDelta *= 2.0;
+        for (unsigned int elevCount=0; elevCount<m_elevResolution; ++elevCount)
+	    {
+            for (unsigned int azimCount=0; azimCount<m_azimResolution; ++azimCount)
+		    {
+                int subElevCount, subAzimCount;
+                glBegin(GL_POLYGON);
+                for (subElevCount=0; subElevCount<m_subdiv; ++subElevCount) {
+                    double nx, ny, nz;
+			        nx = cos(-azimDelta*azimCount*m_subdiv) * cos(elevDelta*(elevCount*m_subdiv+subElevCount));
+			        ny = sin(elevDelta*(elevCount*m_subdiv+subElevCount));
+			        nz = sin(-azimDelta*azimCount*m_subdiv) * cos(elevDelta*(elevCount*m_subdiv+subElevCount));
+			        glNormal3d(-nx, -ny, -nz);
+			        glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+                }
+                for (subAzimCount=0; subAzimCount<m_subdiv; ++subAzimCount) {
+                    double nx, ny, nz;
+			        nx = cos(-azimDelta*(azimCount*m_subdiv+subAzimCount)) * cos(elevDelta*(elevCount+1)*m_subdiv);
+			        ny = sin(elevDelta*(elevCount+1)*m_subdiv);
+			        nz = sin(-azimDelta*(azimCount*m_subdiv+subAzimCount)) * cos(elevDelta*(elevCount+1)*m_subdiv);
+			        glNormal3d(-nx, -ny, -nz);
+			        glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+                }
+                for (subElevCount=0; subElevCount<m_subdiv; ++subElevCount) {
+                    double nx, ny, nz;
+			        nx = cos(-azimDelta*(azimCount+1)*m_subdiv) * cos(elevDelta*((elevCount+1)*m_subdiv-subElevCount));
+			        ny = sin(elevDelta*((elevCount+1)*m_subdiv-subElevCount));
+			        nz = sin(-azimDelta*(azimCount+1)*m_subdiv) * cos(elevDelta*((elevCount+1)*m_subdiv-subElevCount));
+			        glNormal3d(-nx, -ny, -nz);
+			        glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+                }
+                for (subAzimCount=0; subAzimCount<m_subdiv; ++subAzimCount) {
+                    double nx, ny, nz;
+			        nx = cos(-azimDelta*((azimCount+1)*m_subdiv-subAzimCount)) * cos(elevDelta*elevCount*m_subdiv);
+			        ny = sin(elevDelta*elevCount*m_subdiv);
+			        nz = sin(-azimDelta*((azimCount+1)*m_subdiv-subAzimCount)) * cos(elevDelta*elevCount*m_subdiv);
+			        glNormal3d(-nx, -ny, -nz);
+			        glVertex3d(m_radius * nx, m_radius * ny, m_radius * nz);
+                }
+                glEnd();
+		    }
+        }
+    }
+}
Index: projectionDesigner/trunk/projdesigner/src/screen/ScreenModel.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/screen/ScreenModel.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/screen/ScreenModel.cpp	(revision 4)
@@ -0,0 +1,143 @@
+#include "screen/ScreenModel.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pScreen Screen data.
+ */
+ScreenModel::ScreenModel(Screen* pScreen) : ScreenShape(pScreen)
+{
+    m_pModel = NULL;
+    m_modelIndex = 0;
+	m_pScreen = pScreen;
+}
+
+/**
+ * Destructor.
+ */
+ScreenModel::~ScreenModel()
+{
+    if (m_pModel)
+        glmDelete(m_pModel);
+    if (glIsList(m_modelIndex))
+        glDeleteLists(m_modelIndex, 1);
+}
+
+/**
+ * Load a model file.
+ *
+ * @param fileName File name of a model to load.
+ */
+void ScreenModel::setFileName(const QString& fileName)
+{
+    m_fileName = fileName;
+
+    if (m_pModel)
+        glmDelete(m_pModel);
+    if (glIsList(m_modelIndex))
+        glDeleteLists(m_modelIndex, 1);
+
+    m_pModel = glmReadOBJ(fileName.toLocal8Bit().data());
+    glmFacetNormals(m_pModel);
+    glmVertexNormals(m_pModel, 89.5f);
+    m_modelIndex = glGenLists(1);
+    glNewList(m_modelIndex, GL_COMPILE);
+    glmDraw(m_pModel, GLM_SMOOTH);
+    glEndList();
+
+    notifyRedraw();
+}
+
+/**
+ * Retrieve file name of the model.
+ *
+ * @return File name of the model.
+ */
+QString ScreenModel::getFileName() const
+{
+    return m_fileName;
+}
+
+/**
+ * Retrieve bounding box of the screen shape.
+ *
+ * @param min One corner of the screen shape.
+ * @param max Another corner of the screen shape.
+ */
+void ScreenModel::getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max)
+{
+    if (m_pModel)
+    {
+        GLfloat scale[3];
+        glmDimensions(m_pModel, scale);
+        min.set(-scale[0]/2.0f, -scale[1]/2.0f, -scale[2]/2.0f);
+        max.set( scale[0]/2.0f,  scale[1]/2.0f,  scale[2]/2.0f);
+    }
+}
+
+/**
+ * Restore the screen shape from XML data.
+ *
+ * @param element Parent XML element of the screen shape data.
+ */
+bool ScreenModel::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+		if( element.attribute("fileName").isEmpty() )
+		{
+			return true;
+		}
+		else if( QFile::exists(element.attribute("fileName")) )
+		{
+			setFileName(element.attribute("fileName"));
+		}
+		else
+		{
+			QString tmp = element.attribute("fileName");
+			QMessageBox::critical( m_pScreen->getProjectionModel()->getGUI()->getMainWindow(), "Screen model file not found", "Error loading screen model: '"
+				+element.attribute("fileName")+"' does not exist.<br><br>Please put the model file on the appropriate location or modify the project file!" );
+
+			return false;
+		}
+        notifyRedraw();
+    }
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current screen shape as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen shape data as XML data.
+ */
+QDomElement ScreenModel::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.setAttribute("name", getName());
+    de.setAttribute("fileName", m_fileName);
+
+    return de;
+}
+
+/**
+ * Draw the shape model in inherited class.
+ *
+ * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+ */
+void ScreenModel::drawShape(bool)
+{
+    glPushAttrib(GL_ENABLE_BIT);
+
+    if (m_modelIndex)
+    {
+        glDisable(GL_CULL_FACE);
+        glCallList(m_modelIndex);
+    }
+
+    glPopAttrib();
+}
Index: projectionDesigner/trunk/projdesigner/src/screen/ScreenPlane.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/screen/ScreenPlane.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/screen/ScreenPlane.cpp	(revision 4)
@@ -0,0 +1,152 @@
+#include "screen/ScreenPlane.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pScreen Screen data.
+ */
+ScreenPlane::ScreenPlane(Screen* pScreen) : ScreenShape(pScreen)
+{
+    m_width = 2.0;
+    m_height = 2.0;
+    m_horResolution = 4;
+    m_vertResolution = 4;
+}
+
+/**
+ * Destructor.
+ */
+ScreenPlane::~ScreenPlane()
+{
+}
+
+/**
+ * Set width of the plane screen.
+ *
+ * @param width Width of the plane screen.
+ */
+void ScreenPlane::setWidth(double width)
+{
+    if (m_width != width)
+    {
+        m_width = width;
+        notifyRedraw();
+    }
+}
+
+/**
+ * Set height of the plane screen.
+ *
+ * @param height Height of the plane screen.
+ */
+void ScreenPlane::setHeight(double height)
+{
+    if (m_height != height)
+    {
+        m_height = height;
+        notifyRedraw();
+    }
+}
+
+/**
+ * Set horizontal resolution of the plane screen.
+ *
+ * @param resolution Horizontal resolution of the plane screen.
+ */
+void ScreenPlane::setHorResolution(unsigned int resolution)
+{
+    m_horResolution = resolution;
+    notifyRedraw();
+}
+
+/**
+ * Set vertical resolution of the plane screen.
+ *
+ * @param resolution Vertical resolution of the plane screen.
+ */
+void ScreenPlane::setVertResolution(unsigned int resolution)
+{
+    m_vertResolution = resolution;
+    notifyRedraw();
+}
+
+/**
+ * Retrieve bounding box of the screen shape.
+ *
+ * @param min One corner of the screen shape.
+ * @param max Another corner of the screen shape.
+ */
+void ScreenPlane::getBoundingBox(gmtl::Vec3f& min, gmtl::Vec3f& max)
+{
+    min.set((float)-m_width/2.0f, (float)-m_height/2.0f, 0.0f);
+    max.set((float)m_width/2.0f, (float)m_height/2.0f, 0.0f);
+}
+
+/**
+ * Restore the screen shape from XML data.
+ *
+ * @param element Parent XML element of the screen shape data.
+ */
+bool ScreenPlane::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+        m_width = element.attribute("width").toFloat();
+        m_height = element.attribute("height").toFloat();
+        m_horResolution = element.attribute("horResolution").toInt();
+        m_vertResolution = element.attribute("vertResolution").toInt();
+        // if change
+        notifyRedraw();
+    }
+
+	return true;	// todo: secure this function and return false on any critical error
+}
+
+/**
+ * Store the current screen shape as XML data.
+ *
+ * @param name XML node name of the data.
+ * @param doc XML document to store the data.
+ * @return Current screen shape data as XML data.
+ */
+QDomElement ScreenPlane::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = doc.createElement(name);
+    de.setAttribute("name", getName());
+    de.setAttribute("width", m_width);
+    de.setAttribute("height", m_height);
+    de.setAttribute("horResolution", m_horResolution);
+    de.setAttribute("vertResolution", m_vertResolution);
+
+    return de;
+}
+
+/**
+ * Draw the shape model in inherited class.
+ *
+ * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+ */
+void ScreenPlane::drawShape(bool)
+{
+    double horDelta = m_width / m_horResolution;
+    double vertDelta = m_height / m_vertResolution;
+
+    for (unsigned int vertCount=0; vertCount<m_vertResolution; ++vertCount)
+    {
+        glBegin(GL_QUAD_STRIP);
+        for (unsigned int horCount=0; horCount<=m_horResolution; ++horCount)
+        {
+            glNormal3d(0, 0, 1);
+            glVertex3d(m_width/2.0 - horDelta*horCount,
+                       -m_height/2.0 + vertDelta*vertCount,
+                       0.0);
+            glNormal3d(0, 0, 1);
+            glVertex3d(m_width/2.0 - horDelta*(horCount),
+                       -m_height/2.0 + vertDelta*(vertCount+1),
+                       0.0);
+        }
+        glEnd();
+    }
+}
Index: projectionDesigner/trunk/projdesigner/src/screen/ScreenShape.cpp
===================================================================
--- projectionDesigner/trunk/projdesigner/src/screen/ScreenShape.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesigner/src/screen/ScreenShape.cpp	(revision 4)
@@ -0,0 +1,70 @@
+#include "Screen.h"
+#include "screen/ScreenShape.h"
+
+using namespace projection;
+
+/**
+ * Constructor.
+ *
+ * @param pScreen Screen data.
+ */
+ScreenShape::ScreenShape(Screen* pScreen)
+{
+    m_pScreen = pScreen;
+
+    m_dlIndex = 0;
+    m_bDirty = true;
+}
+
+/**
+ * Destructor.
+ */
+ScreenShape::~ScreenShape()
+{
+    if (glIsList(m_dlIndex))
+        glDeleteLists(m_dlIndex, 2);
+}
+
+/**
+ * Draw the shape model in inherited class.
+ *
+ * @param bFrame True to draw a wire frame mesh. False to draw as a polygon model.
+ */
+void ScreenShape::draw(bool bFrame)
+{
+    // cache the model in display lists.
+
+    // update screen shape model, if modified
+    if (m_bDirty)
+    {
+        if (glIsList(m_dlIndex))
+            glDeleteLists(m_dlIndex, 2);
+
+        m_dlIndex = glGenLists(2);
+
+        glNewList(m_dlIndex, GL_COMPILE);
+        drawShape(false);
+        glEndList();
+
+        glNewList(m_dlIndex+1, GL_COMPILE);
+        drawShape(true);
+        glEndList();
+
+        m_bDirty = false;
+    }
+
+    if (!bFrame)
+        glCallList(m_dlIndex);
+    else
+        glCallList(m_dlIndex+1);
+}
+
+/**
+ * Notify to redraw the screen shape.
+ */
+void ScreenShape::notifyRedraw()
+{
+    m_bDirty = true;
+
+    m_pScreen->notifyRedraw();
+}
Index: projectionDesigner/trunk/projdesigner/ui_qchannelmanagerwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qchannelmanagerwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qchannelmanagerwidget.h	(revision 4)
@@ -0,0 +1,114 @@
+/********************************************************************************
+** Form generated from reading ui file 'qchannelmanagerwidget.ui'
+**
+** Created: Mon 27. Apr 14:25:46 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QCHANNELMANAGERWIDGET_H
+#define UI_QCHANNELMANAGERWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QTableWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QChannelManagerWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QVBoxLayout *vboxLayout;
+    QTableWidget *channelTable;
+    QHBoxLayout *hboxLayout1;
+    QSpacerItem *spacerItem;
+    QPushButton *addButton;
+    QPushButton *removeButton;
+
+    void setupUi(QWidget *QChannelManagerWidget)
+    {
+        if (QChannelManagerWidget->objectName().isEmpty())
+            QChannelManagerWidget->setObjectName(QString::fromUtf8("QChannelManagerWidget"));
+        QChannelManagerWidget->resize(223, 236);
+        hboxLayout = new QHBoxLayout(QChannelManagerWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        channelTable = new QTableWidget(QChannelManagerWidget);
+        channelTable->setObjectName(QString::fromUtf8("channelTable"));
+        channelTable->setSelectionMode(QAbstractItemView::SingleSelection);
+        channelTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+
+        vboxLayout->addWidget(channelTable);
+
+        hboxLayout1 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(0);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        spacerItem = new QSpacerItem(16, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout1->addItem(spacerItem);
+
+        addButton = new QPushButton(QChannelManagerWidget);
+        addButton->setObjectName(QString::fromUtf8("addButton"));
+        addButton->setFocusPolicy(Qt::NoFocus);
+
+        hboxLayout1->addWidget(addButton);
+
+        removeButton = new QPushButton(QChannelManagerWidget);
+        removeButton->setObjectName(QString::fromUtf8("removeButton"));
+        removeButton->setFocusPolicy(Qt::NoFocus);
+
+        hboxLayout1->addWidget(removeButton);
+
+
+        vboxLayout->addLayout(hboxLayout1);
+
+
+        hboxLayout->addLayout(vboxLayout);
+
+
+        retranslateUi(QChannelManagerWidget);
+
+        QMetaObject::connectSlotsByName(QChannelManagerWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QChannelManagerWidget)
+    {
+        QChannelManagerWidget->setWindowTitle(QApplication::translate("QChannelManagerWidget", "Channel Manager", 0, QApplication::UnicodeUTF8));
+        addButton->setText(QApplication::translate("QChannelManagerWidget", "Add", 0, QApplication::UnicodeUTF8));
+        removeButton->setText(QApplication::translate("QChannelManagerWidget", "Remove", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QChannelManagerWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QChannelManagerWidget: public Ui_QChannelManagerWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QCHANNELMANAGERWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qchannelwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qchannelwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qchannelwidget.h	(revision 4)
@@ -0,0 +1,514 @@
+/********************************************************************************
+** Form generated from reading ui file 'qchannelwidget.ui'
+**
+** Created: Tue 28. Apr 15:36:10 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QCHANNELWIDGET_H
+#define UI_QCHANNELWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QSpinBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+#include "gui/QProjectionMatrixWidget.h"
+#include "gui/QTransformMatrixWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QChannelWidget
+{
+public:
+    QVBoxLayout *vboxLayout;
+    QHBoxLayout *hboxLayout;
+    QLabel *nameLabel;
+    QLineEdit *nameEdit;
+    QSpacerItem *spacerItem;
+    QGroupBox *overlayGroupBox;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout1;
+    QCheckBox *overlayNameCheckBox;
+    QHBoxLayout *hboxLayout2;
+    QLabel *overlayImageLabel;
+    QLineEdit *overlayImageEdit;
+    QPushButton *overlayImageBrowseButton;
+    QToolBox *toolBox;
+    QWidget *page;
+    QHBoxLayout *hboxLayout3;
+    QVBoxLayout *vboxLayout2;
+    QHBoxLayout *hboxLayout4;
+    QLabel *remoteHostNameLabel;
+    QLineEdit *remoteHostNameEdit;
+    QHBoxLayout *hboxLayout5;
+    QCheckBox *remoteFullScreenCheckBox;
+    QLabel *remoteScreenLabel;
+    QComboBox *remoteScreenComboBox;
+    QSpacerItem *spacerItem1;
+    QWidget *page_2;
+    QVBoxLayout *vboxLayout3;
+    QHBoxLayout *hboxLayout6;
+    QLabel *pluginLabel;
+    QComboBox *pluginComboBox;
+    QSpacerItem *spacerItem2;
+    QStackedWidget *stackedWidget;
+    projection::QTransformMatrixWidget *projectionTransformWidget;
+    QGroupBox *warpGroupBox;
+    QHBoxLayout *hboxLayout7;
+    QHBoxLayout *hboxLayout8;
+    QCheckBox *warpCheckBox;
+    QLabel *warpResLabel;
+    QSpinBox *warpResSpinBox;
+    QPushButton *warpResetButton;
+    QHBoxLayout *hboxLayout9;
+    QSpacerItem *spacerItem3;
+    QPushButton *calibrateButton;
+    QSpacerItem *spacerItem4;
+    QWidget *page_3;
+    QVBoxLayout *vboxLayout4;
+    QVBoxLayout *vboxLayout5;
+    projection::QProjectionMatrixWidget *viewProjectionWidget;
+    projection::QTransformMatrixWidget *viewTransformWidget;
+    QHBoxLayout *hboxLayout10;
+    QSpacerItem *spacerItem5;
+    QPushButton *fitButton;
+    QSpacerItem *spacerItem6;
+    QSpacerItem *spacerItem7;
+    QHBoxLayout *hboxLayout11;
+    QSpacerItem *spacerItem8;
+    QPushButton *windowButton;
+
+    void setupUi(QWidget *QChannelWidget)
+    {
+        if (QChannelWidget->objectName().isEmpty())
+            QChannelWidget->setObjectName(QString::fromUtf8("QChannelWidget"));
+        QChannelWidget->resize(232, 508);
+        vboxLayout = new QVBoxLayout(QChannelWidget);
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+        vboxLayout->setMargin(0);
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        hboxLayout = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout->setMargin(0);
+#endif
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        nameLabel = new QLabel(QChannelWidget);
+        nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
+
+        hboxLayout->addWidget(nameLabel);
+
+        nameEdit = new QLineEdit(QChannelWidget);
+        nameEdit->setObjectName(QString::fromUtf8("nameEdit"));
+
+        hboxLayout->addWidget(nameEdit);
+
+        spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout->addItem(spacerItem);
+
+
+        vboxLayout->addLayout(hboxLayout);
+
+        overlayGroupBox = new QGroupBox(QChannelWidget);
+        overlayGroupBox->setObjectName(QString::fromUtf8("overlayGroupBox"));
+        hboxLayout1 = new QHBoxLayout(overlayGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout1 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout1->setMargin(0);
+#endif
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        overlayNameCheckBox = new QCheckBox(overlayGroupBox);
+        overlayNameCheckBox->setObjectName(QString::fromUtf8("overlayNameCheckBox"));
+
+        vboxLayout1->addWidget(overlayNameCheckBox);
+
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+        hboxLayout2->setMargin(0);
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        overlayImageLabel = new QLabel(overlayGroupBox);
+        overlayImageLabel->setObjectName(QString::fromUtf8("overlayImageLabel"));
+
+        hboxLayout2->addWidget(overlayImageLabel);
+
+        overlayImageEdit = new QLineEdit(overlayGroupBox);
+        overlayImageEdit->setObjectName(QString::fromUtf8("overlayImageEdit"));
+        QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(overlayImageEdit->sizePolicy().hasHeightForWidth());
+        overlayImageEdit->setSizePolicy(sizePolicy);
+
+        hboxLayout2->addWidget(overlayImageEdit);
+
+        overlayImageBrowseButton = new QPushButton(overlayGroupBox);
+        overlayImageBrowseButton->setObjectName(QString::fromUtf8("overlayImageBrowseButton"));
+        QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
+        sizePolicy1.setHorizontalStretch(0);
+        sizePolicy1.setVerticalStretch(0);
+        sizePolicy1.setHeightForWidth(overlayImageBrowseButton->sizePolicy().hasHeightForWidth());
+        overlayImageBrowseButton->setSizePolicy(sizePolicy1);
+        overlayImageBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        hboxLayout2->addWidget(overlayImageBrowseButton);
+
+
+        vboxLayout1->addLayout(hboxLayout2);
+
+
+        hboxLayout1->addLayout(vboxLayout1);
+
+
+        vboxLayout->addWidget(overlayGroupBox);
+
+        toolBox = new QToolBox(QChannelWidget);
+        toolBox->setObjectName(QString::fromUtf8("toolBox"));
+        toolBox->setAutoFillBackground(true);
+        page = new QWidget();
+        page->setObjectName(QString::fromUtf8("page"));
+        page->setGeometry(QRect(0, 0, 232, 198));
+        hboxLayout3 = new QHBoxLayout(page);
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(0);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        vboxLayout2 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout2->setMargin(0);
+#endif
+        vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout4->setMargin(0);
+#endif
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        remoteHostNameLabel = new QLabel(page);
+        remoteHostNameLabel->setObjectName(QString::fromUtf8("remoteHostNameLabel"));
+
+        hboxLayout4->addWidget(remoteHostNameLabel);
+
+        remoteHostNameEdit = new QLineEdit(page);
+        remoteHostNameEdit->setObjectName(QString::fromUtf8("remoteHostNameEdit"));
+
+        hboxLayout4->addWidget(remoteHostNameEdit);
+
+
+        vboxLayout2->addLayout(hboxLayout4);
+
+        hboxLayout5 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout5->setSpacing(6);
+#endif
+        hboxLayout5->setMargin(0);
+        hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
+        remoteFullScreenCheckBox = new QCheckBox(page);
+        remoteFullScreenCheckBox->setObjectName(QString::fromUtf8("remoteFullScreenCheckBox"));
+
+        hboxLayout5->addWidget(remoteFullScreenCheckBox);
+
+        remoteScreenLabel = new QLabel(page);
+        remoteScreenLabel->setObjectName(QString::fromUtf8("remoteScreenLabel"));
+
+        hboxLayout5->addWidget(remoteScreenLabel);
+
+        remoteScreenComboBox = new QComboBox(page);
+        remoteScreenComboBox->setObjectName(QString::fromUtf8("remoteScreenComboBox"));
+
+        hboxLayout5->addWidget(remoteScreenComboBox);
+
+
+        vboxLayout2->addLayout(hboxLayout5);
+
+        spacerItem1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout2->addItem(spacerItem1);
+
+
+        hboxLayout3->addLayout(vboxLayout2);
+
+        toolBox->addItem(page, QString::fromUtf8("Remote Settings"));
+        page_2 = new QWidget();
+        page_2->setObjectName(QString::fromUtf8("page_2"));
+        page_2->setGeometry(QRect(0, 0, 232, 262));
+        vboxLayout3 = new QVBoxLayout(page_2);
+        vboxLayout3->setSpacing(0);
+        vboxLayout3->setMargin(0);
+        vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
+        hboxLayout6 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout6->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout6->setMargin(0);
+#endif
+        hboxLayout6->setObjectName(QString::fromUtf8("hboxLayout6"));
+        pluginLabel = new QLabel(page_2);
+        pluginLabel->setObjectName(QString::fromUtf8("pluginLabel"));
+
+        hboxLayout6->addWidget(pluginLabel);
+
+        pluginComboBox = new QComboBox(page_2);
+        pluginComboBox->setObjectName(QString::fromUtf8("pluginComboBox"));
+
+        hboxLayout6->addWidget(pluginComboBox);
+
+        spacerItem2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout6->addItem(spacerItem2);
+
+
+        vboxLayout3->addLayout(hboxLayout6);
+
+        stackedWidget = new QStackedWidget(page_2);
+        stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
+        stackedWidget->setMinimumSize(QSize(0, 150));
+
+        vboxLayout3->addWidget(stackedWidget);
+
+        projectionTransformWidget = new projection::QTransformMatrixWidget(page_2);
+        projectionTransformWidget->setObjectName(QString::fromUtf8("projectionTransformWidget"));
+        projectionTransformWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout3->addWidget(projectionTransformWidget);
+
+        warpGroupBox = new QGroupBox(page_2);
+        warpGroupBox->setObjectName(QString::fromUtf8("warpGroupBox"));
+        hboxLayout7 = new QHBoxLayout(warpGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout7->setSpacing(6);
+#endif
+        hboxLayout7->setMargin(4);
+        hboxLayout7->setObjectName(QString::fromUtf8("hboxLayout7"));
+        hboxLayout8 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout8->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout8->setMargin(0);
+#endif
+        hboxLayout8->setObjectName(QString::fromUtf8("hboxLayout8"));
+        warpCheckBox = new QCheckBox(warpGroupBox);
+        warpCheckBox->setObjectName(QString::fromUtf8("warpCheckBox"));
+
+        hboxLayout8->addWidget(warpCheckBox);
+
+        warpResLabel = new QLabel(warpGroupBox);
+        warpResLabel->setObjectName(QString::fromUtf8("warpResLabel"));
+
+        hboxLayout8->addWidget(warpResLabel);
+
+        warpResSpinBox = new QSpinBox(warpGroupBox);
+        warpResSpinBox->setObjectName(QString::fromUtf8("warpResSpinBox"));
+        warpResSpinBox->setMaximumSize(QSize(32, 16777215));
+        warpResSpinBox->setMinimum(2);
+        warpResSpinBox->setMaximum(8);
+
+        hboxLayout8->addWidget(warpResSpinBox);
+
+        warpResetButton = new QPushButton(warpGroupBox);
+        warpResetButton->setObjectName(QString::fromUtf8("warpResetButton"));
+        warpResetButton->setMaximumSize(QSize(50, 16777215));
+
+        hboxLayout8->addWidget(warpResetButton);
+
+
+        hboxLayout7->addLayout(hboxLayout8);
+
+
+        vboxLayout3->addWidget(warpGroupBox);
+
+        hboxLayout9 = new QHBoxLayout();
+        hboxLayout9->setSpacing(0);
+        hboxLayout9->setMargin(0);
+        hboxLayout9->setObjectName(QString::fromUtf8("hboxLayout9"));
+        spacerItem3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout9->addItem(spacerItem3);
+
+        calibrateButton = new QPushButton(page_2);
+        calibrateButton->setObjectName(QString::fromUtf8("calibrateButton"));
+        calibrateButton->setEnabled(false);
+
+        hboxLayout9->addWidget(calibrateButton);
+
+
+        vboxLayout3->addLayout(hboxLayout9);
+
+        spacerItem4 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout3->addItem(spacerItem4);
+
+        toolBox->addItem(page_2, QString::fromUtf8("Projector"));
+        page_3 = new QWidget();
+        page_3->setObjectName(QString::fromUtf8("page_3"));
+        page_3->setGeometry(QRect(0, 0, 232, 349));
+        vboxLayout4 = new QVBoxLayout(page_3);
+        vboxLayout4->setSpacing(0);
+        vboxLayout4->setMargin(0);
+        vboxLayout4->setObjectName(QString::fromUtf8("vboxLayout4"));
+        vboxLayout5 = new QVBoxLayout();
+        vboxLayout5->setSpacing(0);
+#ifndef Q_OS_MAC
+        vboxLayout5->setMargin(0);
+#endif
+        vboxLayout5->setObjectName(QString::fromUtf8("vboxLayout5"));
+        viewProjectionWidget = new projection::QProjectionMatrixWidget(page_3);
+        viewProjectionWidget->setObjectName(QString::fromUtf8("viewProjectionWidget"));
+        viewProjectionWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout5->addWidget(viewProjectionWidget);
+
+        viewTransformWidget = new projection::QTransformMatrixWidget(page_3);
+        viewTransformWidget->setObjectName(QString::fromUtf8("viewTransformWidget"));
+        viewTransformWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout5->addWidget(viewTransformWidget);
+
+        hboxLayout10 = new QHBoxLayout();
+        hboxLayout10->setSpacing(0);
+        hboxLayout10->setMargin(0);
+        hboxLayout10->setObjectName(QString::fromUtf8("hboxLayout10"));
+        spacerItem5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout10->addItem(spacerItem5);
+
+        fitButton = new QPushButton(page_3);
+        fitButton->setObjectName(QString::fromUtf8("fitButton"));
+        fitButton->setEnabled(false);
+
+        hboxLayout10->addWidget(fitButton);
+
+
+        vboxLayout5->addLayout(hboxLayout10);
+
+        spacerItem6 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout5->addItem(spacerItem6);
+
+
+        vboxLayout4->addLayout(vboxLayout5);
+
+        toolBox->addItem(page_3, QString::fromUtf8("View"));
+
+        vboxLayout->addWidget(toolBox);
+
+        spacerItem7 = new QSpacerItem(190, 16, QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+        vboxLayout->addItem(spacerItem7);
+
+        hboxLayout11 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout11->setSpacing(6);
+#endif
+        hboxLayout11->setMargin(0);
+        hboxLayout11->setObjectName(QString::fromUtf8("hboxLayout11"));
+        spacerItem8 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout11->addItem(spacerItem8);
+
+        windowButton = new QPushButton(QChannelWidget);
+        windowButton->setObjectName(QString::fromUtf8("windowButton"));
+        QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Fixed);
+        sizePolicy2.setHorizontalStretch(0);
+        sizePolicy2.setVerticalStretch(0);
+        sizePolicy2.setHeightForWidth(windowButton->sizePolicy().hasHeightForWidth());
+        windowButton->setSizePolicy(sizePolicy2);
+        windowButton->setFocusPolicy(Qt::NoFocus);
+
+        hboxLayout11->addWidget(windowButton);
+
+
+        vboxLayout->addLayout(hboxLayout11);
+
+        QWidget::setTabOrder(nameEdit, remoteHostNameEdit);
+        QWidget::setTabOrder(remoteHostNameEdit, remoteFullScreenCheckBox);
+        QWidget::setTabOrder(remoteFullScreenCheckBox, remoteScreenComboBox);
+        QWidget::setTabOrder(remoteScreenComboBox, windowButton);
+
+        retranslateUi(QChannelWidget);
+
+        toolBox->setCurrentIndex(1);
+
+
+        QMetaObject::connectSlotsByName(QChannelWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QChannelWidget)
+    {
+        QChannelWidget->setWindowTitle(QApplication::translate("QChannelWidget", "Channel Settings", 0, QApplication::UnicodeUTF8));
+        nameLabel->setText(QApplication::translate("QChannelWidget", "Name", 0, QApplication::UnicodeUTF8));
+        overlayGroupBox->setTitle(QApplication::translate("QChannelWidget", "Overlay", 0, QApplication::UnicodeUTF8));
+        overlayNameCheckBox->setText(QApplication::translate("QChannelWidget", "Channel name", 0, QApplication::UnicodeUTF8));
+        overlayImageLabel->setText(QApplication::translate("QChannelWidget", "Image", 0, QApplication::UnicodeUTF8));
+        overlayImageBrowseButton->setText(QApplication::translate("QChannelWidget", "...", 0, QApplication::UnicodeUTF8));
+        remoteHostNameLabel->setText(QApplication::translate("QChannelWidget", "Host name", 0, QApplication::UnicodeUTF8));
+        remoteFullScreenCheckBox->setText(QApplication::translate("QChannelWidget", "Full screen", 0, QApplication::UnicodeUTF8));
+        remoteScreenLabel->setText(QApplication::translate("QChannelWidget", " Screen", 0, QApplication::UnicodeUTF8));
+        remoteScreenComboBox->clear();
+        remoteScreenComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QChannelWidget", "1", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QChannelWidget", "2", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QChannelWidget", "3", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QChannelWidget", "4", 0, QApplication::UnicodeUTF8)
+        );
+        toolBox->setItemText(toolBox->indexOf(page), QApplication::translate("QChannelWidget", "Remote Settings", 0, QApplication::UnicodeUTF8));
+        pluginLabel->setText(QApplication::translate("QChannelWidget", "Plugin", 0, QApplication::UnicodeUTF8));
+        warpGroupBox->setTitle(QApplication::translate("QChannelWidget", "Warp", 0, QApplication::UnicodeUTF8));
+        warpCheckBox->setText(QApplication::translate("QChannelWidget", "Enable", 0, QApplication::UnicodeUTF8));
+        warpResLabel->setText(QApplication::translate("QChannelWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        warpResetButton->setText(QApplication::translate("QChannelWidget", "Reset", 0, QApplication::UnicodeUTF8));
+        calibrateButton->setText(QApplication::translate("QChannelWidget", "Calibrate...", 0, QApplication::UnicodeUTF8));
+        toolBox->setItemText(toolBox->indexOf(page_2), QApplication::translate("QChannelWidget", "Projector", 0, QApplication::UnicodeUTF8));
+        fitButton->setText(QApplication::translate("QChannelWidget", "Fit to Projector", 0, QApplication::UnicodeUTF8));
+        toolBox->setItemText(toolBox->indexOf(page_3), QApplication::translate("QChannelWidget", "View", 0, QApplication::UnicodeUTF8));
+        windowButton->setText(QApplication::translate("QChannelWidget", "Open Window...", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QChannelWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QChannelWidget: public Ui_QChannelWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QCHANNELWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qclientwindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qclientwindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qclientwindow.h	(revision 4)
@@ -0,0 +1,91 @@
+/********************************************************************************
+** Form generated from reading ui file 'qclientwindow.ui'
+**
+** Created: Mon 27. Apr 14:25:56 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QCLIENTWINDOW_H
+#define UI_QCLIENTWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QTextEdit>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QClientWindow
+{
+public:
+    QAction *actionFileExit;
+    QWidget *centralWidget;
+    QHBoxLayout *hboxLayout;
+    QTextEdit *logEdit;
+    QMenuBar *menuBar;
+    QMenu *menu_File;
+
+    void setupUi(QMainWindow *QClientWindow)
+    {
+        if (QClientWindow->objectName().isEmpty())
+            QClientWindow->setObjectName(QString::fromUtf8("QClientWindow"));
+        QClientWindow->resize(344, 254);
+        actionFileExit = new QAction(QClientWindow);
+        actionFileExit->setObjectName(QString::fromUtf8("actionFileExit"));
+        centralWidget = new QWidget(QClientWindow);
+        centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+        hboxLayout = new QHBoxLayout(centralWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(2);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        logEdit = new QTextEdit(centralWidget);
+        logEdit->setObjectName(QString::fromUtf8("logEdit"));
+        logEdit->setAcceptDrops(false);
+        logEdit->setReadOnly(true);
+        logEdit->setAcceptRichText(false);
+
+        hboxLayout->addWidget(logEdit);
+
+        QClientWindow->setCentralWidget(centralWidget);
+        menuBar = new QMenuBar(QClientWindow);
+        menuBar->setObjectName(QString::fromUtf8("menuBar"));
+        menuBar->setGeometry(QRect(0, 0, 344, 18));
+        menu_File = new QMenu(menuBar);
+        menu_File->setObjectName(QString::fromUtf8("menu_File"));
+        QClientWindow->setMenuBar(menuBar);
+
+        menuBar->addAction(menu_File->menuAction());
+        menu_File->addAction(actionFileExit);
+
+        retranslateUi(QClientWindow);
+
+        QMetaObject::connectSlotsByName(QClientWindow);
+    } // setupUi
+
+    void retranslateUi(QMainWindow *QClientWindow)
+    {
+        QClientWindow->setWindowTitle(QApplication::translate("QClientWindow", "Projection Designer", 0, QApplication::UnicodeUTF8));
+        actionFileExit->setText(QApplication::translate("QClientWindow", "E&xit", 0, QApplication::UnicodeUTF8));
+        menu_File->setTitle(QApplication::translate("QClientWindow", "&File", 0, QApplication::UnicodeUTF8));
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QClientWindow: public Ui_QClientWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QCLIENTWINDOW_H
Index: projectionDesigner/trunk/projdesigner/ui_qdesignviewwindow.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qdesignviewwindow.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qdesignviewwindow.h	(revision 4)
@@ -0,0 +1,338 @@
+/********************************************************************************
+** Form generated from reading ui file 'qdesignviewwindow.ui'
+**
+** Created: Wed 2. Sep 15:07:30 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QDESIGNVIEWWINDOW_H
+#define UI_QDESIGNVIEWWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QSplitter>
+#include <QtGui/QWidget>
+#include "gui/QDesignViewWidget.h"
+#include "gui/QPanelWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QDesignViewWindow
+{
+public:
+    QAction *actionFileNew;
+    QAction *actionFileOpen;
+    QAction *actionFileSave;
+    QAction *actionFileSaveAs;
+    QAction *actionFileSyncClients;
+    QAction *actionFileExit;
+    QAction *actionFileExitAll;
+    QAction *actionEditDesignDistortionMap;
+    QAction *actionEditDesignBlendMap;
+    QAction *actionEditPreference;
+    QAction *actionViewPerspective;
+    QAction *actionViewCenter;
+    QAction *actionViewTop;
+    QAction *actionViewSide;
+    QAction *actionViewFront;
+    QAction *actionViewAxis;
+    QAction *actionViewGrid;
+    QAction *actionViewInfo;
+    QAction *actionViewViewAll;
+    QAction *actionWindowSceneViewer;
+    QAction *actionWindowSceneDialog;
+    QAction *actionWindowScreenDialog;
+    QAction *actionWindowChannelManager;
+    QAction *actionHelpHelp;
+    QAction *actionHelpAbout;
+    QAction *actionFileExportDataset;
+    QAction *actionHelpPlugins;
+    QAction *actionHelpAbout_Qt;
+    QWidget *centralWidget;
+    QHBoxLayout *hboxLayout;
+    QSplitter *splitter;
+    projection::QDesignViewWidget *designViewWidget;
+    projection::QPanelWidget *panelWidget;
+    QMenuBar *menuBar;
+    QMenu *menuEdit;
+    QMenu *menuView;
+    QMenu *menuWindow;
+    QMenu *menuFile;
+    QMenu *menuHelp;
+
+    void setupUi(QMainWindow *QDesignViewWindow)
+    {
+        if (QDesignViewWindow->objectName().isEmpty())
+            QDesignViewWindow->setObjectName(QString::fromUtf8("QDesignViewWindow"));
+        QDesignViewWindow->resize(960, 700);
+        QIcon icon;
+        icon.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/projDesigner.png")), QIcon::Normal, QIcon::Off);
+        QDesignViewWindow->setWindowIcon(icon);
+        actionFileNew = new QAction(QDesignViewWindow);
+        actionFileNew->setObjectName(QString::fromUtf8("actionFileNew"));
+        QIcon icon1;
+        icon1.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/new.png")), QIcon::Normal, QIcon::Off);
+        actionFileNew->setIcon(icon1);
+        actionFileOpen = new QAction(QDesignViewWindow);
+        actionFileOpen->setObjectName(QString::fromUtf8("actionFileOpen"));
+        QIcon icon2;
+        icon2.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/open.png")), QIcon::Normal, QIcon::Off);
+        actionFileOpen->setIcon(icon2);
+        actionFileSave = new QAction(QDesignViewWindow);
+        actionFileSave->setObjectName(QString::fromUtf8("actionFileSave"));
+        QIcon icon3;
+        icon3.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/save.png")), QIcon::Normal, QIcon::Off);
+        actionFileSave->setIcon(icon3);
+        actionFileSaveAs = new QAction(QDesignViewWindow);
+        actionFileSaveAs->setObjectName(QString::fromUtf8("actionFileSaveAs"));
+        QIcon icon4;
+        icon4.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/saveAs.png")), QIcon::Normal, QIcon::Off);
+        actionFileSaveAs->setIcon(icon4);
+        actionFileSyncClients = new QAction(QDesignViewWindow);
+        actionFileSyncClients->setObjectName(QString::fromUtf8("actionFileSyncClients"));
+        QIcon icon5;
+        icon5.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/sync.png")), QIcon::Normal, QIcon::Off);
+        actionFileSyncClients->setIcon(icon5);
+        actionFileExit = new QAction(QDesignViewWindow);
+        actionFileExit->setObjectName(QString::fromUtf8("actionFileExit"));
+        QIcon icon6;
+        icon6.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/exit.png")), QIcon::Normal, QIcon::Off);
+        actionFileExit->setIcon(icon6);
+        actionFileExitAll = new QAction(QDesignViewWindow);
+        actionFileExitAll->setObjectName(QString::fromUtf8("actionFileExitAll"));
+        QIcon icon7;
+        icon7.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/exitAll.png")), QIcon::Normal, QIcon::Off);
+        actionFileExitAll->setIcon(icon7);
+        actionEditDesignDistortionMap = new QAction(QDesignViewWindow);
+        actionEditDesignDistortionMap->setObjectName(QString::fromUtf8("actionEditDesignDistortionMap"));
+        QIcon icon8;
+        icon8.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/distortionMode.png")), QIcon::Normal, QIcon::Off);
+        actionEditDesignDistortionMap->setIcon(icon8);
+        actionEditDesignDistortionMap->setShortcutContext(Qt::ApplicationShortcut);
+        actionEditDesignBlendMap = new QAction(QDesignViewWindow);
+        actionEditDesignBlendMap->setObjectName(QString::fromUtf8("actionEditDesignBlendMap"));
+        QIcon icon9;
+        icon9.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/blendMode.png")), QIcon::Normal, QIcon::Off);
+        actionEditDesignBlendMap->setIcon(icon9);
+        actionEditDesignBlendMap->setShortcutContext(Qt::ApplicationShortcut);
+        actionEditPreference = new QAction(QDesignViewWindow);
+        actionEditPreference->setObjectName(QString::fromUtf8("actionEditPreference"));
+        QIcon icon10;
+        icon10.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/settings.png")), QIcon::Normal, QIcon::Off);
+        actionEditPreference->setIcon(icon10);
+        actionEditPreference->setShortcutContext(Qt::ApplicationShortcut);
+        actionViewPerspective = new QAction(QDesignViewWindow);
+        actionViewPerspective->setObjectName(QString::fromUtf8("actionViewPerspective"));
+        actionViewCenter = new QAction(QDesignViewWindow);
+        actionViewCenter->setObjectName(QString::fromUtf8("actionViewCenter"));
+        actionViewTop = new QAction(QDesignViewWindow);
+        actionViewTop->setObjectName(QString::fromUtf8("actionViewTop"));
+        actionViewSide = new QAction(QDesignViewWindow);
+        actionViewSide->setObjectName(QString::fromUtf8("actionViewSide"));
+        actionViewFront = new QAction(QDesignViewWindow);
+        actionViewFront->setObjectName(QString::fromUtf8("actionViewFront"));
+        actionViewAxis = new QAction(QDesignViewWindow);
+        actionViewAxis->setObjectName(QString::fromUtf8("actionViewAxis"));
+        actionViewGrid = new QAction(QDesignViewWindow);
+        actionViewGrid->setObjectName(QString::fromUtf8("actionViewGrid"));
+        actionViewInfo = new QAction(QDesignViewWindow);
+        actionViewInfo->setObjectName(QString::fromUtf8("actionViewInfo"));
+        actionViewViewAll = new QAction(QDesignViewWindow);
+        actionViewViewAll->setObjectName(QString::fromUtf8("actionViewViewAll"));
+        actionWindowSceneViewer = new QAction(QDesignViewWindow);
+        actionWindowSceneViewer->setObjectName(QString::fromUtf8("actionWindowSceneViewer"));
+        actionWindowSceneDialog = new QAction(QDesignViewWindow);
+        actionWindowSceneDialog->setObjectName(QString::fromUtf8("actionWindowSceneDialog"));
+        actionWindowScreenDialog = new QAction(QDesignViewWindow);
+        actionWindowScreenDialog->setObjectName(QString::fromUtf8("actionWindowScreenDialog"));
+        actionWindowChannelManager = new QAction(QDesignViewWindow);
+        actionWindowChannelManager->setObjectName(QString::fromUtf8("actionWindowChannelManager"));
+        actionHelpHelp = new QAction(QDesignViewWindow);
+        actionHelpHelp->setObjectName(QString::fromUtf8("actionHelpHelp"));
+        QIcon icon11;
+        icon11.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/help.png")), QIcon::Normal, QIcon::Off);
+        actionHelpHelp->setIcon(icon11);
+        actionHelpAbout = new QAction(QDesignViewWindow);
+        actionHelpAbout->setObjectName(QString::fromUtf8("actionHelpAbout"));
+        actionHelpAbout->setIcon(icon);
+        actionFileExportDataset = new QAction(QDesignViewWindow);
+        actionFileExportDataset->setObjectName(QString::fromUtf8("actionFileExportDataset"));
+        QIcon icon12;
+        icon12.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/export.png")), QIcon::Normal, QIcon::Off);
+        actionFileExportDataset->setIcon(icon12);
+        actionHelpPlugins = new QAction(QDesignViewWindow);
+        actionHelpPlugins->setObjectName(QString::fromUtf8("actionHelpPlugins"));
+        QIcon icon13;
+        icon13.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/plugins.png")), QIcon::Normal, QIcon::Off);
+        actionHelpPlugins->setIcon(icon13);
+        actionHelpAbout_Qt = new QAction(QDesignViewWindow);
+        actionHelpAbout_Qt->setObjectName(QString::fromUtf8("actionHelpAbout_Qt"));
+        QIcon icon14;
+        icon14.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/aboutQt.png")), QIcon::Normal, QIcon::Off);
+        actionHelpAbout_Qt->setIcon(icon14);
+        centralWidget = new QWidget(QDesignViewWindow);
+        centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+        hboxLayout = new QHBoxLayout(centralWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        splitter = new QSplitter(centralWidget);
+        splitter->setObjectName(QString::fromUtf8("splitter"));
+        splitter->setOrientation(Qt::Horizontal);
+        designViewWidget = new projection::QDesignViewWidget(splitter);
+        designViewWidget->setObjectName(QString::fromUtf8("designViewWidget"));
+        QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
+        sizePolicy.setHorizontalStretch(1);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(designViewWidget->sizePolicy().hasHeightForWidth());
+        designViewWidget->setSizePolicy(sizePolicy);
+        splitter->addWidget(designViewWidget);
+        panelWidget = new projection::QPanelWidget(splitter);
+        panelWidget->setObjectName(QString::fromUtf8("panelWidget"));
+        QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
+        sizePolicy1.setHorizontalStretch(0);
+        sizePolicy1.setVerticalStretch(0);
+        sizePolicy1.setHeightForWidth(panelWidget->sizePolicy().hasHeightForWidth());
+        panelWidget->setSizePolicy(sizePolicy1);
+        splitter->addWidget(panelWidget);
+
+        hboxLayout->addWidget(splitter);
+
+        QDesignViewWindow->setCentralWidget(centralWidget);
+        menuBar = new QMenuBar(QDesignViewWindow);
+        menuBar->setObjectName(QString::fromUtf8("menuBar"));
+        menuBar->setGeometry(QRect(0, 0, 960, 22));
+        menuEdit = new QMenu(menuBar);
+        menuEdit->setObjectName(QString::fromUtf8("menuEdit"));
+        menuView = new QMenu(menuBar);
+        menuView->setObjectName(QString::fromUtf8("menuView"));
+        menuWindow = new QMenu(menuBar);
+        menuWindow->setObjectName(QString::fromUtf8("menuWindow"));
+        menuFile = new QMenu(menuBar);
+        menuFile->setObjectName(QString::fromUtf8("menuFile"));
+        menuHelp = new QMenu(menuBar);
+        menuHelp->setObjectName(QString::fromUtf8("menuHelp"));
+        QDesignViewWindow->setMenuBar(menuBar);
+
+        menuBar->addAction(menuFile->menuAction());
+        menuBar->addAction(menuEdit->menuAction());
+        menuBar->addAction(menuView->menuAction());
+        menuBar->addAction(menuWindow->menuAction());
+        menuBar->addAction(menuHelp->menuAction());
+        menuEdit->addAction(actionEditDesignDistortionMap);
+        menuEdit->addAction(actionEditDesignBlendMap);
+        menuEdit->addSeparator();
+        menuEdit->addAction(actionEditPreference);
+        menuView->addAction(actionViewPerspective);
+        menuView->addAction(actionViewCenter);
+        menuView->addAction(actionViewFront);
+        menuView->addAction(actionViewTop);
+        menuView->addAction(actionViewSide);
+        menuView->addSeparator();
+        menuView->addAction(actionViewAxis);
+        menuView->addAction(actionViewGrid);
+        menuView->addAction(actionViewInfo);
+        menuView->addSeparator();
+        menuView->addAction(actionViewViewAll);
+        menuWindow->addAction(actionWindowSceneViewer);
+        menuWindow->addSeparator();
+        menuWindow->addAction(actionWindowSceneDialog);
+        menuWindow->addAction(actionWindowScreenDialog);
+        menuWindow->addAction(actionWindowChannelManager);
+        menuFile->addAction(actionFileNew);
+        menuFile->addAction(actionFileOpen);
+        menuFile->addAction(actionFileSave);
+        menuFile->addAction(actionFileSaveAs);
+        menuFile->addSeparator();
+        menuFile->addAction(actionFileExportDataset);
+        menuFile->addSeparator();
+        menuFile->addAction(actionFileSyncClients);
+        menuHelp->addAction(actionHelpHelp);
+        menuHelp->addAction(actionHelpPlugins);
+        menuHelp->addSeparator();
+        menuHelp->addAction(actionHelpAbout);
+        menuHelp->addAction(actionHelpAbout_Qt);
+
+        retranslateUi(QDesignViewWindow);
+
+        QMetaObject::connectSlotsByName(QDesignViewWindow);
+    } // setupUi
+
+    void retranslateUi(QMainWindow *QDesignViewWindow)
+    {
+        QDesignViewWindow->setWindowTitle(QApplication::translate("QDesignViewWindow", "Projection Designer", 0, QApplication::UnicodeUTF8));
+        actionFileNew->setText(QApplication::translate("QDesignViewWindow", "&New Project", 0, QApplication::UnicodeUTF8));
+        actionFileNew->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+N", 0, QApplication::UnicodeUTF8));
+        actionFileOpen->setText(QApplication::translate("QDesignViewWindow", "&Open Project...", 0, QApplication::UnicodeUTF8));
+        actionFileOpen->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+O", 0, QApplication::UnicodeUTF8));
+        actionFileSave->setText(QApplication::translate("QDesignViewWindow", "&Save Project", 0, QApplication::UnicodeUTF8));
+        actionFileSave->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+S", 0, QApplication::UnicodeUTF8));
+        actionFileSaveAs->setText(QApplication::translate("QDesignViewWindow", "Save Project &As...", 0, QApplication::UnicodeUTF8));
+        actionFileSaveAs->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+A", 0, QApplication::UnicodeUTF8));
+        actionFileSyncClients->setText(QApplication::translate("QDesignViewWindow", "Sync Clients", 0, QApplication::UnicodeUTF8));
+        actionFileSyncClients->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+Y", 0, QApplication::UnicodeUTF8));
+        actionFileExit->setText(QApplication::translate("QDesignViewWindow", "Exit", 0, QApplication::UnicodeUTF8));
+        actionFileExit->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+Q", 0, QApplication::UnicodeUTF8));
+        actionFileExitAll->setText(QApplication::translate("QDesignViewWindow", "Exit All", 0, QApplication::UnicodeUTF8));
+        actionFileExitAll->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+W", 0, QApplication::UnicodeUTF8));
+        actionEditDesignDistortionMap->setText(QApplication::translate("QDesignViewWindow", "&Distortion Map", 0, QApplication::UnicodeUTF8));
+        actionEditDesignDistortionMap->setShortcut(QApplication::translate("QDesignViewWindow", "Alt+D", 0, QApplication::UnicodeUTF8));
+        actionEditDesignBlendMap->setText(QApplication::translate("QDesignViewWindow", "Blend Map", 0, QApplication::UnicodeUTF8));
+        actionEditDesignBlendMap->setShortcut(QApplication::translate("QDesignViewWindow", "Alt+B", 0, QApplication::UnicodeUTF8));
+        actionEditPreference->setText(QApplication::translate("QDesignViewWindow", "Preferences", 0, QApplication::UnicodeUTF8));
+        actionEditPreference->setIconText(QApplication::translate("QDesignViewWindow", "Preferences", 0, QApplication::UnicodeUTF8));
+#ifndef QT_NO_TOOLTIP
+        actionEditPreference->setToolTip(QApplication::translate("QDesignViewWindow", "Preferences", 0, QApplication::UnicodeUTF8));
+#endif // QT_NO_TOOLTIP
+#ifndef QT_NO_STATUSTIP
+        actionEditPreference->setStatusTip(QApplication::translate("QDesignViewWindow", "Opens the preferences dialog", 0, QApplication::UnicodeUTF8));
+#endif // QT_NO_STATUSTIP
+        actionEditPreference->setShortcut(QApplication::translate("QDesignViewWindow", "Alt+P", 0, QApplication::UnicodeUTF8));
+        actionViewPerspective->setText(QApplication::translate("QDesignViewWindow", "&Perspective", 0, QApplication::UnicodeUTF8));
+        actionViewCenter->setText(QApplication::translate("QDesignViewWindow", "&Center", 0, QApplication::UnicodeUTF8));
+        actionViewTop->setText(QApplication::translate("QDesignViewWindow", "Top", 0, QApplication::UnicodeUTF8));
+        actionViewSide->setText(QApplication::translate("QDesignViewWindow", "Side", 0, QApplication::UnicodeUTF8));
+        actionViewFront->setText(QApplication::translate("QDesignViewWindow", "Front", 0, QApplication::UnicodeUTF8));
+        actionViewAxis->setText(QApplication::translate("QDesignViewWindow", "&Axis", 0, QApplication::UnicodeUTF8));
+        actionViewGrid->setText(QApplication::translate("QDesignViewWindow", "&Grid", 0, QApplication::UnicodeUTF8));
+        actionViewInfo->setText(QApplication::translate("QDesignViewWindow", "&Info", 0, QApplication::UnicodeUTF8));
+        actionViewViewAll->setText(QApplication::translate("QDesignViewWindow", "View All", 0, QApplication::UnicodeUTF8));
+        actionWindowSceneViewer->setText(QApplication::translate("QDesignViewWindow", "Scene Viewer", 0, QApplication::UnicodeUTF8));
+        actionWindowSceneDialog->setText(QApplication::translate("QDesignViewWindow", "Scene", 0, QApplication::UnicodeUTF8));
+        actionWindowScreenDialog->setText(QApplication::translate("QDesignViewWindow", "Screen", 0, QApplication::UnicodeUTF8));
+        actionWindowChannelManager->setText(QApplication::translate("QDesignViewWindow", "Channels", 0, QApplication::UnicodeUTF8));
+        actionHelpHelp->setText(QApplication::translate("QDesignViewWindow", "Help...", 0, QApplication::UnicodeUTF8));
+        actionHelpHelp->setShortcut(QApplication::translate("QDesignViewWindow", "F1", 0, QApplication::UnicodeUTF8));
+        actionHelpAbout->setText(QApplication::translate("QDesignViewWindow", "About Projection Designer", 0, QApplication::UnicodeUTF8));
+        actionFileExportDataset->setText(QApplication::translate("QDesignViewWindow", "Export Data set", 0, QApplication::UnicodeUTF8));
+        actionFileExportDataset->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+E", 0, QApplication::UnicodeUTF8));
+        actionHelpPlugins->setText(QApplication::translate("QDesignViewWindow", "Plugins...", 0, QApplication::UnicodeUTF8));
+        actionHelpPlugins->setShortcut(QApplication::translate("QDesignViewWindow", "Ctrl+Alt+P", 0, QApplication::UnicodeUTF8));
+        actionHelpAbout_Qt->setText(QApplication::translate("QDesignViewWindow", "About Qt", 0, QApplication::UnicodeUTF8));
+        menuEdit->setTitle(QApplication::translate("QDesignViewWindow", "&Edit", 0, QApplication::UnicodeUTF8));
+        menuView->setTitle(QApplication::translate("QDesignViewWindow", "&View", 0, QApplication::UnicodeUTF8));
+        menuWindow->setTitle(QApplication::translate("QDesignViewWindow", "&Window", 0, QApplication::UnicodeUTF8));
+        menuFile->setTitle(QApplication::translate("QDesignViewWindow", "&File", 0, QApplication::UnicodeUTF8));
+        menuHelp->setTitle(QApplication::translate("QDesignViewWindow", "&Help", 0, QApplication::UnicodeUTF8));
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QDesignViewWindow: public Ui_QDesignViewWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QDESIGNVIEWWINDOW_H
Index: projectionDesigner/trunk/projdesigner/ui_qpanelwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qpanelwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qpanelwidget.h	(revision 4)
@@ -0,0 +1,184 @@
+/********************************************************************************
+** Form generated from reading ui file 'qpanelwidget.ui'
+**
+** Created: Mon 27. Apr 14:25:47 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QPANELWIDGET_H
+#define UI_QPANELWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QTabWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+#include "gui/QChannelManagerWidget.h"
+#include "gui/QChannelWidget.h"
+#include "gui/QSceneWidget.h"
+#include "gui/QScreenWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QPanelWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QTabWidget *tabWidget;
+    QWidget *channelsTab;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout;
+    projection::QChannelManagerWidget *channelManager;
+    QGroupBox *channelGroup;
+    QHBoxLayout *hboxLayout2;
+    projection::QChannelWidget *channel;
+    QSpacerItem *spacerItem;
+    QWidget *screenTab;
+    QVBoxLayout *vboxLayout1;
+    projection::QScreenWidget *screen;
+    QSpacerItem *spacerItem1;
+    QWidget *sceneTab;
+    QVBoxLayout *vboxLayout2;
+    projection::QSceneWidget *scene;
+    QSpacerItem *spacerItem2;
+
+    void setupUi(QWidget *QPanelWidget)
+    {
+        if (QPanelWidget->objectName().isEmpty())
+            QPanelWidget->setObjectName(QString::fromUtf8("QPanelWidget"));
+        QPanelWidget->resize(196, 722);
+        hboxLayout = new QHBoxLayout(QPanelWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        tabWidget = new QTabWidget(QPanelWidget);
+        tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
+        channelsTab = new QWidget();
+        channelsTab->setObjectName(QString::fromUtf8("channelsTab"));
+        hboxLayout1 = new QHBoxLayout(channelsTab);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        channelManager = new projection::QChannelManagerWidget(channelsTab);
+        channelManager->setObjectName(QString::fromUtf8("channelManager"));
+        channelManager->setMaximumSize(QSize(16777215, 160));
+        channelManager->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout->addWidget(channelManager);
+
+        channelGroup = new QGroupBox(channelsTab);
+        channelGroup->setObjectName(QString::fromUtf8("channelGroup"));
+        QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(channelGroup->sizePolicy().hasHeightForWidth());
+        channelGroup->setSizePolicy(sizePolicy);
+        hboxLayout2 = new QHBoxLayout(channelGroup);
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+        hboxLayout2->setMargin(4);
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        channel = new projection::QChannelWidget(channelGroup);
+        channel->setObjectName(QString::fromUtf8("channel"));
+        channel->setFocusPolicy(Qt::StrongFocus);
+
+        hboxLayout2->addWidget(channel);
+
+
+        vboxLayout->addWidget(channelGroup);
+
+        spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout->addItem(spacerItem);
+
+
+        hboxLayout1->addLayout(vboxLayout);
+
+        tabWidget->addTab(channelsTab, QString());
+        screenTab = new QWidget();
+        screenTab->setObjectName(QString::fromUtf8("screenTab"));
+        vboxLayout1 = new QVBoxLayout(screenTab);
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+        vboxLayout1->setMargin(0);
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        screen = new projection::QScreenWidget(screenTab);
+        screen->setObjectName(QString::fromUtf8("screen"));
+
+        vboxLayout1->addWidget(screen);
+
+        spacerItem1 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout1->addItem(spacerItem1);
+
+        tabWidget->addTab(screenTab, QString());
+        sceneTab = new QWidget();
+        sceneTab->setObjectName(QString::fromUtf8("sceneTab"));
+        vboxLayout2 = new QVBoxLayout(sceneTab);
+#ifndef Q_OS_MAC
+        vboxLayout2->setSpacing(6);
+#endif
+        vboxLayout2->setMargin(0);
+        vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+        scene = new projection::QSceneWidget(sceneTab);
+        scene->setObjectName(QString::fromUtf8("scene"));
+
+        vboxLayout2->addWidget(scene);
+
+        spacerItem2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout2->addItem(spacerItem2);
+
+        tabWidget->addTab(sceneTab, QString());
+
+        hboxLayout->addWidget(tabWidget);
+
+        QWidget::setTabOrder(channelManager, channel);
+        QWidget::setTabOrder(channel, tabWidget);
+
+        retranslateUi(QPanelWidget);
+
+        QMetaObject::connectSlotsByName(QPanelWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QPanelWidget)
+    {
+        QPanelWidget->setWindowTitle(QApplication::translate("QPanelWidget", "Projection Designer", 0, QApplication::UnicodeUTF8));
+        channelGroup->setTitle(QApplication::translate("QPanelWidget", "Channel", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(channelsTab), QApplication::translate("QPanelWidget", "Channels", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(screenTab), QApplication::translate("QPanelWidget", "Screen", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(sceneTab), QApplication::translate("QPanelWidget", "Scene", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QPanelWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QPanelWidget: public Ui_QPanelWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QPANELWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qpreferencedialog.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qpreferencedialog.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qpreferencedialog.h	(revision 4)
@@ -0,0 +1,475 @@
+/********************************************************************************
+** Form generated from reading ui file 'qpreferencedialog.ui'
+**
+** Created: Tue 28. Apr 15:36:09 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QPREFERENCEDIALOG_H
+#define UI_QPREFERENCEDIALOG_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QDialog>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QSpinBox>
+#include <QtGui/QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QPreferenceDialog
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QVBoxLayout *vboxLayout;
+    QGroupBox *gridGroupBox;
+    QHBoxLayout *hboxLayout1;
+    QHBoxLayout *hboxLayout2;
+    QLabel *gridSizeLabel;
+    QLineEdit *gridSizeEdit;
+    QLabel *gridSubdivLabel;
+    QSpinBox *gridSubdivSpinBox;
+    QSpacerItem *spacerItem;
+    QGroupBox *offscreenSceneRenderingGroupBox;
+    QHBoxLayout *hboxLayout3;
+    QVBoxLayout *vboxLayout1;
+    QHBoxLayout *hboxLayout4;
+    QLabel *bufferSizeLabel;
+    QComboBox *bufferWidthComboBox;
+    QComboBox *bufferHeightComboBox;
+    QSpacerItem *spacerItem1;
+    QGroupBox *blendMapGroupBox;
+    QHBoxLayout *hboxLayout5;
+    QVBoxLayout *vboxLayout2;
+    QHBoxLayout *hboxLayout6;
+    QCheckBox *softEdgeCheckBox;
+    QLabel *blendEdgeWidthLabel;
+    QSpinBox *blendEdgeWidthSpinBox;
+    QLabel *blendEdgeExponentLabel;
+    QLineEdit *blendEdgeExponentEdit;
+    QSpacerItem *spacerItem2;
+    QGroupBox *exportGroupBox;
+    QHBoxLayout *hboxLayout7;
+    QVBoxLayout *vboxLayout3;
+    QHBoxLayout *hboxLayout8;
+    QLabel *exportSizeLabel;
+    QComboBox *exportWidthComboBox;
+    QComboBox *exportHeightComboBox;
+    QSpacerItem *spacerItem3;
+    QLabel *exportFileNamePatternLabel;
+    QHBoxLayout *hboxLayout9;
+    QSpacerItem *spacerItem4;
+    QGridLayout *gridLayout;
+    QLabel *exportDistortMapPatternLabel;
+    QLabel *exportViewMatrixPatternLabel;
+    QLineEdit *exportDistortMapPatternEdit;
+    QLineEdit *exportViewMatrixPatternEdit;
+    QLineEdit *exportBlendMapPatternEdit;
+    QLabel *exportBlendMapPatternLabel;
+    QSpacerItem *spacerItem5;
+    QSpacerItem *spacerItem6;
+    QPushButton *pB_ClosePrefDiag;
+
+    void setupUi(QDialog *QPreferenceDialog)
+    {
+        if (QPreferenceDialog->objectName().isEmpty())
+            QPreferenceDialog->setObjectName(QString::fromUtf8("QPreferenceDialog"));
+        QPreferenceDialog->resize(345, 357);
+        QIcon icon;
+        icon.addPixmap(QPixmap(QString::fromUtf8(":/new/prefix1/Resources/settings.png")), QIcon::Normal, QIcon::Off);
+        QPreferenceDialog->setWindowIcon(icon);
+        hboxLayout = new QHBoxLayout(QPreferenceDialog);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(4);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        gridGroupBox = new QGroupBox(QPreferenceDialog);
+        gridGroupBox->setObjectName(QString::fromUtf8("gridGroupBox"));
+        hboxLayout1 = new QHBoxLayout(gridGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout2->setMargin(0);
+#endif
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        gridSizeLabel = new QLabel(gridGroupBox);
+        gridSizeLabel->setObjectName(QString::fromUtf8("gridSizeLabel"));
+
+        hboxLayout2->addWidget(gridSizeLabel);
+
+        gridSizeEdit = new QLineEdit(gridGroupBox);
+        gridSizeEdit->setObjectName(QString::fromUtf8("gridSizeEdit"));
+        gridSizeEdit->setMinimumSize(QSize(64, 0));
+        gridSizeEdit->setMaximumSize(QSize(64, 16777215));
+
+        hboxLayout2->addWidget(gridSizeEdit);
+
+        gridSubdivLabel = new QLabel(gridGroupBox);
+        gridSubdivLabel->setObjectName(QString::fromUtf8("gridSubdivLabel"));
+
+        hboxLayout2->addWidget(gridSubdivLabel);
+
+        gridSubdivSpinBox = new QSpinBox(gridGroupBox);
+        gridSubdivSpinBox->setObjectName(QString::fromUtf8("gridSubdivSpinBox"));
+
+        hboxLayout2->addWidget(gridSubdivSpinBox);
+
+        spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout2->addItem(spacerItem);
+
+
+        hboxLayout1->addLayout(hboxLayout2);
+
+
+        vboxLayout->addWidget(gridGroupBox);
+
+        offscreenSceneRenderingGroupBox = new QGroupBox(QPreferenceDialog);
+        offscreenSceneRenderingGroupBox->setObjectName(QString::fromUtf8("offscreenSceneRenderingGroupBox"));
+        hboxLayout3 = new QHBoxLayout(offscreenSceneRenderingGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(4);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        vboxLayout1 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout1->setMargin(0);
+#endif
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout4->setMargin(0);
+#endif
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        bufferSizeLabel = new QLabel(offscreenSceneRenderingGroupBox);
+        bufferSizeLabel->setObjectName(QString::fromUtf8("bufferSizeLabel"));
+
+        hboxLayout4->addWidget(bufferSizeLabel);
+
+        bufferWidthComboBox = new QComboBox(offscreenSceneRenderingGroupBox);
+        bufferWidthComboBox->setObjectName(QString::fromUtf8("bufferWidthComboBox"));
+
+        hboxLayout4->addWidget(bufferWidthComboBox);
+
+        bufferHeightComboBox = new QComboBox(offscreenSceneRenderingGroupBox);
+        bufferHeightComboBox->setObjectName(QString::fromUtf8("bufferHeightComboBox"));
+
+        hboxLayout4->addWidget(bufferHeightComboBox);
+
+        spacerItem1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout4->addItem(spacerItem1);
+
+
+        vboxLayout1->addLayout(hboxLayout4);
+
+
+        hboxLayout3->addLayout(vboxLayout1);
+
+
+        vboxLayout->addWidget(offscreenSceneRenderingGroupBox);
+
+        blendMapGroupBox = new QGroupBox(QPreferenceDialog);
+        blendMapGroupBox->setObjectName(QString::fromUtf8("blendMapGroupBox"));
+        hboxLayout5 = new QHBoxLayout(blendMapGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout5->setSpacing(6);
+#endif
+        hboxLayout5->setMargin(4);
+        hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
+        vboxLayout2 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout2->setMargin(0);
+#endif
+        vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+        hboxLayout6 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout6->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout6->setMargin(0);
+#endif
+        hboxLayout6->setObjectName(QString::fromUtf8("hboxLayout6"));
+        softEdgeCheckBox = new QCheckBox(blendMapGroupBox);
+        softEdgeCheckBox->setObjectName(QString::fromUtf8("softEdgeCheckBox"));
+
+        hboxLayout6->addWidget(softEdgeCheckBox);
+
+        blendEdgeWidthLabel = new QLabel(blendMapGroupBox);
+        blendEdgeWidthLabel->setObjectName(QString::fromUtf8("blendEdgeWidthLabel"));
+        QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(blendEdgeWidthLabel->sizePolicy().hasHeightForWidth());
+        blendEdgeWidthLabel->setSizePolicy(sizePolicy);
+
+        hboxLayout6->addWidget(blendEdgeWidthLabel);
+
+        blendEdgeWidthSpinBox = new QSpinBox(blendMapGroupBox);
+        blendEdgeWidthSpinBox->setObjectName(QString::fromUtf8("blendEdgeWidthSpinBox"));
+
+        hboxLayout6->addWidget(blendEdgeWidthSpinBox);
+
+        blendEdgeExponentLabel = new QLabel(blendMapGroupBox);
+        blendEdgeExponentLabel->setObjectName(QString::fromUtf8("blendEdgeExponentLabel"));
+
+        hboxLayout6->addWidget(blendEdgeExponentLabel);
+
+        blendEdgeExponentEdit = new QLineEdit(blendMapGroupBox);
+        blendEdgeExponentEdit->setObjectName(QString::fromUtf8("blendEdgeExponentEdit"));
+        blendEdgeExponentEdit->setMaximumSize(QSize(32, 16777215));
+
+        hboxLayout6->addWidget(blendEdgeExponentEdit);
+
+        spacerItem2 = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout6->addItem(spacerItem2);
+
+
+        vboxLayout2->addLayout(hboxLayout6);
+
+
+        hboxLayout5->addLayout(vboxLayout2);
+
+
+        vboxLayout->addWidget(blendMapGroupBox);
+
+        exportGroupBox = new QGroupBox(QPreferenceDialog);
+        exportGroupBox->setObjectName(QString::fromUtf8("exportGroupBox"));
+        hboxLayout7 = new QHBoxLayout(exportGroupBox);
+#ifndef Q_OS_MAC
+        hboxLayout7->setSpacing(6);
+#endif
+        hboxLayout7->setMargin(4);
+        hboxLayout7->setObjectName(QString::fromUtf8("hboxLayout7"));
+        vboxLayout3 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout3->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout3->setMargin(0);
+#endif
+        vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
+        hboxLayout8 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout8->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout8->setMargin(0);
+#endif
+        hboxLayout8->setObjectName(QString::fromUtf8("hboxLayout8"));
+        exportSizeLabel = new QLabel(exportGroupBox);
+        exportSizeLabel->setObjectName(QString::fromUtf8("exportSizeLabel"));
+
+        hboxLayout8->addWidget(exportSizeLabel);
+
+        exportWidthComboBox = new QComboBox(exportGroupBox);
+        exportWidthComboBox->setObjectName(QString::fromUtf8("exportWidthComboBox"));
+        exportWidthComboBox->setEditable(true);
+
+        hboxLayout8->addWidget(exportWidthComboBox);
+
+        exportHeightComboBox = new QComboBox(exportGroupBox);
+        exportHeightComboBox->setObjectName(QString::fromUtf8("exportHeightComboBox"));
+        exportHeightComboBox->setEditable(true);
+
+        hboxLayout8->addWidget(exportHeightComboBox);
+
+        spacerItem3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout8->addItem(spacerItem3);
+
+
+        vboxLayout3->addLayout(hboxLayout8);
+
+        exportFileNamePatternLabel = new QLabel(exportGroupBox);
+        exportFileNamePatternLabel->setObjectName(QString::fromUtf8("exportFileNamePatternLabel"));
+
+        vboxLayout3->addWidget(exportFileNamePatternLabel);
+
+        hboxLayout9 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout9->setSpacing(6);
+#endif
+        hboxLayout9->setMargin(0);
+        hboxLayout9->setObjectName(QString::fromUtf8("hboxLayout9"));
+        spacerItem4 = new QSpacerItem(10, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
+
+        hboxLayout9->addItem(spacerItem4);
+
+        gridLayout = new QGridLayout();
+#ifndef Q_OS_MAC
+        gridLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout->setMargin(0);
+#endif
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        exportDistortMapPatternLabel = new QLabel(exportGroupBox);
+        exportDistortMapPatternLabel->setObjectName(QString::fromUtf8("exportDistortMapPatternLabel"));
+
+        gridLayout->addWidget(exportDistortMapPatternLabel, 0, 0, 1, 1);
+
+        exportViewMatrixPatternLabel = new QLabel(exportGroupBox);
+        exportViewMatrixPatternLabel->setObjectName(QString::fromUtf8("exportViewMatrixPatternLabel"));
+
+        gridLayout->addWidget(exportViewMatrixPatternLabel, 2, 0, 1, 1);
+
+        exportDistortMapPatternEdit = new QLineEdit(exportGroupBox);
+        exportDistortMapPatternEdit->setObjectName(QString::fromUtf8("exportDistortMapPatternEdit"));
+        exportDistortMapPatternEdit->setMinimumSize(QSize(180, 0));
+
+        gridLayout->addWidget(exportDistortMapPatternEdit, 0, 1, 1, 1);
+
+        exportViewMatrixPatternEdit = new QLineEdit(exportGroupBox);
+        exportViewMatrixPatternEdit->setObjectName(QString::fromUtf8("exportViewMatrixPatternEdit"));
+
+        gridLayout->addWidget(exportViewMatrixPatternEdit, 2, 1, 1, 1);
+
+        exportBlendMapPatternEdit = new QLineEdit(exportGroupBox);
+        exportBlendMapPatternEdit->setObjectName(QString::fromUtf8("exportBlendMapPatternEdit"));
+
+        gridLayout->addWidget(exportBlendMapPatternEdit, 1, 1, 1, 1);
+
+        exportBlendMapPatternLabel = new QLabel(exportGroupBox);
+        exportBlendMapPatternLabel->setObjectName(QString::fromUtf8("exportBlendMapPatternLabel"));
+
+        gridLayout->addWidget(exportBlendMapPatternLabel, 1, 0, 1, 1);
+
+
+        hboxLayout9->addLayout(gridLayout);
+
+        spacerItem5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout9->addItem(spacerItem5);
+
+
+        vboxLayout3->addLayout(hboxLayout9);
+
+
+        hboxLayout7->addLayout(vboxLayout3);
+
+
+        vboxLayout->addWidget(exportGroupBox);
+
+        spacerItem6 = new QSpacerItem(325, 71, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout->addItem(spacerItem6);
+
+        pB_ClosePrefDiag = new QPushButton(QPreferenceDialog);
+        pB_ClosePrefDiag->setObjectName(QString::fromUtf8("pB_ClosePrefDiag"));
+
+        vboxLayout->addWidget(pB_ClosePrefDiag);
+
+
+        hboxLayout->addLayout(vboxLayout);
+
+
+        retranslateUi(QPreferenceDialog);
+        QObject::connect(pB_ClosePrefDiag, SIGNAL(clicked()), QPreferenceDialog, SLOT(close()));
+
+        QMetaObject::connectSlotsByName(QPreferenceDialog);
+    } // setupUi
+
+    void retranslateUi(QDialog *QPreferenceDialog)
+    {
+        QPreferenceDialog->setWindowTitle(QApplication::translate("QPreferenceDialog", "Preference", 0, QApplication::UnicodeUTF8));
+        gridGroupBox->setTitle(QApplication::translate("QPreferenceDialog", "Grid", 0, QApplication::UnicodeUTF8));
+        gridSizeLabel->setText(QApplication::translate("QPreferenceDialog", "Size", 0, QApplication::UnicodeUTF8));
+        gridSubdivLabel->setText(QApplication::translate("QPreferenceDialog", "Subdivision", 0, QApplication::UnicodeUTF8));
+        offscreenSceneRenderingGroupBox->setTitle(QApplication::translate("QPreferenceDialog", "Off-screen Scene Rendering", 0, QApplication::UnicodeUTF8));
+        bufferSizeLabel->setText(QApplication::translate("QPreferenceDialog", "Buffer size", 0, QApplication::UnicodeUTF8));
+        bufferWidthComboBox->clear();
+        bufferWidthComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QPreferenceDialog", "128", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "256", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "512", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "1024", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "2048", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "4096", 0, QApplication::UnicodeUTF8)
+        );
+        bufferHeightComboBox->clear();
+        bufferHeightComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QPreferenceDialog", "128", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "256", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "512", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "1024", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "2048", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "4096", 0, QApplication::UnicodeUTF8)
+        );
+        blendMapGroupBox->setTitle(QApplication::translate("QPreferenceDialog", "Blend Map", 0, QApplication::UnicodeUTF8));
+        softEdgeCheckBox->setText(QApplication::translate("QPreferenceDialog", "Soft edge", 0, QApplication::UnicodeUTF8));
+        blendEdgeWidthLabel->setText(QApplication::translate("QPreferenceDialog", " Width", 0, QApplication::UnicodeUTF8));
+        blendEdgeExponentLabel->setText(QApplication::translate("QPreferenceDialog", "Exponent", 0, QApplication::UnicodeUTF8));
+        exportGroupBox->setTitle(QApplication::translate("QPreferenceDialog", "Export", 0, QApplication::UnicodeUTF8));
+        exportSizeLabel->setText(QApplication::translate("QPreferenceDialog", "Image size", 0, QApplication::UnicodeUTF8));
+        exportWidthComboBox->clear();
+        exportWidthComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QPreferenceDialog", "256", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "512", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "1024", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "2048", 0, QApplication::UnicodeUTF8)
+        );
+        exportHeightComboBox->clear();
+        exportHeightComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QPreferenceDialog", "256", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "512", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "1024", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QPreferenceDialog", "2048", 0, QApplication::UnicodeUTF8)
+        );
+        exportFileNamePatternLabel->setText(QApplication::translate("QPreferenceDialog", "Export file name pattern", 0, QApplication::UnicodeUTF8));
+        exportDistortMapPatternLabel->setText(QApplication::translate("QPreferenceDialog", "Distortion map file", 0, QApplication::UnicodeUTF8));
+        exportViewMatrixPatternLabel->setText(QApplication::translate("QPreferenceDialog", "View matrix file", 0, QApplication::UnicodeUTF8));
+        exportBlendMapPatternLabel->setText(QApplication::translate("QPreferenceDialog", "Blend map file", 0, QApplication::UnicodeUTF8));
+        pB_ClosePrefDiag->setText(QApplication::translate("QPreferenceDialog", "Close", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QPreferenceDialog);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QPreferenceDialog: public Ui_QPreferenceDialog {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QPREFERENCEDIALOG_H
Index: projectionDesigner/trunk/projdesigner/ui_qprojectionmatrixwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qprojectionmatrixwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qprojectionmatrixwidget.h	(revision 4)
@@ -0,0 +1,207 @@
+/********************************************************************************
+** Form generated from reading ui file 'qprojectionmatrixwidget.ui'
+**
+** Created: Mon 27. Apr 14:25:41 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QPROJECTIONMATRIXWIDGET_H
+#define UI_QPROJECTIONMATRIXWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QProjectionMatrixWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QGroupBox *projectionGroup;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout;
+    QHBoxLayout *hboxLayout2;
+    QLabel *fovLabel;
+    QLineEdit *fovEdit;
+    QLabel *aspectLabel;
+    QLineEdit *aspectRatioEdit;
+    QHBoxLayout *hboxLayout3;
+    QLabel *nearLabel;
+    QLineEdit *nearEdit;
+    QLabel *farLabel;
+    QLineEdit *farEdit;
+    QHBoxLayout *hboxLayout4;
+    QLabel *offaxisLabel;
+    QLabel *offaxisXLabel;
+    QLineEdit *offaxisXEdit;
+    QLabel *offaxisYLabel;
+    QLineEdit *offaxisYEdit;
+
+    void setupUi(QWidget *QProjectionMatrixWidget)
+    {
+        if (QProjectionMatrixWidget->objectName().isEmpty())
+            QProjectionMatrixWidget->setObjectName(QString::fromUtf8("QProjectionMatrixWidget"));
+        QProjectionMatrixWidget->resize(169, 110);
+        hboxLayout = new QHBoxLayout(QProjectionMatrixWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        projectionGroup = new QGroupBox(QProjectionMatrixWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        hboxLayout1 = new QHBoxLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(0);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+        vboxLayout->setMargin(4);
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout2->setMargin(0);
+#endif
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        fovLabel = new QLabel(projectionGroup);
+        fovLabel->setObjectName(QString::fromUtf8("fovLabel"));
+
+        hboxLayout2->addWidget(fovLabel);
+
+        fovEdit = new QLineEdit(projectionGroup);
+        fovEdit->setObjectName(QString::fromUtf8("fovEdit"));
+
+        hboxLayout2->addWidget(fovEdit);
+
+        aspectLabel = new QLabel(projectionGroup);
+        aspectLabel->setObjectName(QString::fromUtf8("aspectLabel"));
+
+        hboxLayout2->addWidget(aspectLabel);
+
+        aspectRatioEdit = new QLineEdit(projectionGroup);
+        aspectRatioEdit->setObjectName(QString::fromUtf8("aspectRatioEdit"));
+
+        hboxLayout2->addWidget(aspectRatioEdit);
+
+
+        vboxLayout->addLayout(hboxLayout2);
+
+        hboxLayout3 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(0);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        nearLabel = new QLabel(projectionGroup);
+        nearLabel->setObjectName(QString::fromUtf8("nearLabel"));
+
+        hboxLayout3->addWidget(nearLabel);
+
+        nearEdit = new QLineEdit(projectionGroup);
+        nearEdit->setObjectName(QString::fromUtf8("nearEdit"));
+
+        hboxLayout3->addWidget(nearEdit);
+
+        farLabel = new QLabel(projectionGroup);
+        farLabel->setObjectName(QString::fromUtf8("farLabel"));
+
+        hboxLayout3->addWidget(farLabel);
+
+        farEdit = new QLineEdit(projectionGroup);
+        farEdit->setObjectName(QString::fromUtf8("farEdit"));
+
+        hboxLayout3->addWidget(farEdit);
+
+
+        vboxLayout->addLayout(hboxLayout3);
+
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+        hboxLayout4->setMargin(0);
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        offaxisLabel = new QLabel(projectionGroup);
+        offaxisLabel->setObjectName(QString::fromUtf8("offaxisLabel"));
+
+        hboxLayout4->addWidget(offaxisLabel);
+
+        offaxisXLabel = new QLabel(projectionGroup);
+        offaxisXLabel->setObjectName(QString::fromUtf8("offaxisXLabel"));
+
+        hboxLayout4->addWidget(offaxisXLabel);
+
+        offaxisXEdit = new QLineEdit(projectionGroup);
+        offaxisXEdit->setObjectName(QString::fromUtf8("offaxisXEdit"));
+
+        hboxLayout4->addWidget(offaxisXEdit);
+
+        offaxisYLabel = new QLabel(projectionGroup);
+        offaxisYLabel->setObjectName(QString::fromUtf8("offaxisYLabel"));
+
+        hboxLayout4->addWidget(offaxisYLabel);
+
+        offaxisYEdit = new QLineEdit(projectionGroup);
+        offaxisYEdit->setObjectName(QString::fromUtf8("offaxisYEdit"));
+
+        hboxLayout4->addWidget(offaxisYEdit);
+
+
+        vboxLayout->addLayout(hboxLayout4);
+
+
+        hboxLayout1->addLayout(vboxLayout);
+
+
+        hboxLayout->addWidget(projectionGroup);
+
+        QWidget::setTabOrder(fovEdit, aspectRatioEdit);
+        QWidget::setTabOrder(aspectRatioEdit, nearEdit);
+        QWidget::setTabOrder(nearEdit, farEdit);
+
+        retranslateUi(QProjectionMatrixWidget);
+
+        QMetaObject::connectSlotsByName(QProjectionMatrixWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QProjectionMatrixWidget)
+    {
+        QProjectionMatrixWidget->setWindowTitle(QApplication::translate("QProjectionMatrixWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("QProjectionMatrixWidget", "Projection", 0, QApplication::UnicodeUTF8));
+        fovLabel->setText(QApplication::translate("QProjectionMatrixWidget", "FOV", 0, QApplication::UnicodeUTF8));
+        aspectLabel->setText(QApplication::translate("QProjectionMatrixWidget", "Aspect", 0, QApplication::UnicodeUTF8));
+        nearLabel->setText(QApplication::translate("QProjectionMatrixWidget", "Near", 0, QApplication::UnicodeUTF8));
+        farLabel->setText(QApplication::translate("QProjectionMatrixWidget", "Far", 0, QApplication::UnicodeUTF8));
+        offaxisLabel->setText(QApplication::translate("QProjectionMatrixWidget", "Off-axis ", 0, QApplication::UnicodeUTF8));
+        offaxisXLabel->setText(QApplication::translate("QProjectionMatrixWidget", "X", 0, QApplication::UnicodeUTF8));
+        offaxisYLabel->setText(QApplication::translate("QProjectionMatrixWidget", "Y", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QProjectionMatrixWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QProjectionMatrixWidget: public Ui_QProjectionMatrixWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QPROJECTIONMATRIXWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qscenewidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qscenewidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qscenewidget.h	(revision 4)
@@ -0,0 +1,262 @@
+/********************************************************************************
+** Form generated from reading ui file 'qscenewidget.ui'
+**
+** Created: Mon 27. Apr 14:25:31 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QSCENEWIDGET_H
+#define UI_QSCENEWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+#include "gui/QTransformMatrixWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QSceneWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QVBoxLayout *vboxLayout;
+    projection::QTransformMatrixWidget *transformWidget;
+    QGroupBox *contentGroup;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout1;
+    QHBoxLayout *hboxLayout2;
+    QLabel *typeLabel;
+    QComboBox *typeComboBox;
+    QSpacerItem *spacerItem;
+    QStackedWidget *stackedWidget;
+    QCheckBox *showInDesignViewCheckBox;
+    QHBoxLayout *hboxLayout3;
+    QLabel *sceneSizeLabel;
+    QLineEdit *sceneSizeEdit;
+    QSpacerItem *spacerItem1;
+    QHBoxLayout *hboxLayout4;
+    QCheckBox *gridCheckBox;
+    QLabel *gridSizeLabel;
+    QLineEdit *gridSizeEdit;
+    QSpacerItem *spacerItem2;
+    QHBoxLayout *hboxLayout5;
+    QSpacerItem *spacerItem3;
+    QPushButton *centerViewButton;
+    QPushButton *viewAllButton;
+
+    void setupUi(QWidget *QSceneWidget)
+    {
+        if (QSceneWidget->objectName().isEmpty())
+            QSceneWidget->setObjectName(QString::fromUtf8("QSceneWidget"));
+        QSceneWidget->resize(178, 242);
+        hboxLayout = new QHBoxLayout(QSceneWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(4);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        transformWidget = new projection::QTransformMatrixWidget(QSceneWidget);
+        transformWidget->setObjectName(QString::fromUtf8("transformWidget"));
+        transformWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout->addWidget(transformWidget);
+
+        contentGroup = new QGroupBox(QSceneWidget);
+        contentGroup->setObjectName(QString::fromUtf8("contentGroup"));
+        hboxLayout1 = new QHBoxLayout(contentGroup);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout1 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout1->setMargin(0);
+#endif
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout2->setMargin(0);
+#endif
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        typeLabel = new QLabel(contentGroup);
+        typeLabel->setObjectName(QString::fromUtf8("typeLabel"));
+
+        hboxLayout2->addWidget(typeLabel);
+
+        typeComboBox = new QComboBox(contentGroup);
+        typeComboBox->setObjectName(QString::fromUtf8("typeComboBox"));
+        typeComboBox->setMinimumSize(QSize(96, 0));
+
+        hboxLayout2->addWidget(typeComboBox);
+
+        spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout2->addItem(spacerItem);
+
+
+        vboxLayout1->addLayout(hboxLayout2);
+
+        stackedWidget = new QStackedWidget(contentGroup);
+        stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
+        stackedWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout1->addWidget(stackedWidget);
+
+
+        hboxLayout1->addLayout(vboxLayout1);
+
+
+        vboxLayout->addWidget(contentGroup);
+
+        showInDesignViewCheckBox = new QCheckBox(QSceneWidget);
+        showInDesignViewCheckBox->setObjectName(QString::fromUtf8("showInDesignViewCheckBox"));
+
+        vboxLayout->addWidget(showInDesignViewCheckBox);
+
+        hboxLayout3 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(0);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        sceneSizeLabel = new QLabel(QSceneWidget);
+        sceneSizeLabel->setObjectName(QString::fromUtf8("sceneSizeLabel"));
+
+        hboxLayout3->addWidget(sceneSizeLabel);
+
+        sceneSizeEdit = new QLineEdit(QSceneWidget);
+        sceneSizeEdit->setObjectName(QString::fromUtf8("sceneSizeEdit"));
+        sceneSizeEdit->setMaximumSize(QSize(64, 16777215));
+
+        hboxLayout3->addWidget(sceneSizeEdit);
+
+        spacerItem1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout3->addItem(spacerItem1);
+
+
+        vboxLayout->addLayout(hboxLayout3);
+
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+        hboxLayout4->setMargin(0);
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        gridCheckBox = new QCheckBox(QSceneWidget);
+        gridCheckBox->setObjectName(QString::fromUtf8("gridCheckBox"));
+
+        hboxLayout4->addWidget(gridCheckBox);
+
+        gridSizeLabel = new QLabel(QSceneWidget);
+        gridSizeLabel->setObjectName(QString::fromUtf8("gridSizeLabel"));
+
+        hboxLayout4->addWidget(gridSizeLabel);
+
+        gridSizeEdit = new QLineEdit(QSceneWidget);
+        gridSizeEdit->setObjectName(QString::fromUtf8("gridSizeEdit"));
+        gridSizeEdit->setMaximumSize(QSize(64, 16777215));
+
+        hboxLayout4->addWidget(gridSizeEdit);
+
+        spacerItem2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout4->addItem(spacerItem2);
+
+
+        vboxLayout->addLayout(hboxLayout4);
+
+        hboxLayout5 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout5->setSpacing(6);
+#endif
+        hboxLayout5->setMargin(0);
+        hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
+        spacerItem3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout5->addItem(spacerItem3);
+
+        centerViewButton = new QPushButton(QSceneWidget);
+        centerViewButton->setObjectName(QString::fromUtf8("centerViewButton"));
+
+        hboxLayout5->addWidget(centerViewButton);
+
+        viewAllButton = new QPushButton(QSceneWidget);
+        viewAllButton->setObjectName(QString::fromUtf8("viewAllButton"));
+
+        hboxLayout5->addWidget(viewAllButton);
+
+
+        vboxLayout->addLayout(hboxLayout5);
+
+
+        hboxLayout->addLayout(vboxLayout);
+
+        QWidget::setTabOrder(typeComboBox, stackedWidget);
+        QWidget::setTabOrder(stackedWidget, showInDesignViewCheckBox);
+        QWidget::setTabOrder(showInDesignViewCheckBox, gridCheckBox);
+        QWidget::setTabOrder(gridCheckBox, gridSizeEdit);
+        QWidget::setTabOrder(gridSizeEdit, centerViewButton);
+        QWidget::setTabOrder(centerViewButton, viewAllButton);
+
+        retranslateUi(QSceneWidget);
+
+        stackedWidget->setCurrentIndex(-1);
+
+
+        QMetaObject::connectSlotsByName(QSceneWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QSceneWidget)
+    {
+        QSceneWidget->setWindowTitle(QApplication::translate("QSceneWidget", "Scene Settings", 0, QApplication::UnicodeUTF8));
+        contentGroup->setTitle(QApplication::translate("QSceneWidget", "Content", 0, QApplication::UnicodeUTF8));
+        typeLabel->setText(QApplication::translate("QSceneWidget", "Type", 0, QApplication::UnicodeUTF8));
+        showInDesignViewCheckBox->setText(QApplication::translate("QSceneWidget", "Show in Design View", 0, QApplication::UnicodeUTF8));
+        sceneSizeLabel->setText(QApplication::translate("QSceneWidget", "Scene size", 0, QApplication::UnicodeUTF8));
+        gridCheckBox->setText(QApplication::translate("QSceneWidget", "Grid", 0, QApplication::UnicodeUTF8));
+        gridSizeLabel->setText(QApplication::translate("QSceneWidget", "Size", 0, QApplication::UnicodeUTF8));
+        centerViewButton->setText(QApplication::translate("QSceneWidget", "Center View", 0, QApplication::UnicodeUTF8));
+        viewAllButton->setText(QApplication::translate("QSceneWidget", "ViewAll", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QSceneWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QSceneWidget: public Ui_QSceneWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QSCENEWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qscreenwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qscreenwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qscreenwidget.h	(revision 4)
@@ -0,0 +1,630 @@
+/********************************************************************************
+** Form generated from reading ui file 'qscreenwidget.ui'
+**
+** Created: Mon 27. Apr 14:25:27 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QSCREENWIDGET_H
+#define UI_QSCREENWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QSpinBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+#include "gui/QTransformMatrixWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QScreenWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QVBoxLayout *vboxLayout;
+    projection::QTransformMatrixWidget *transformWidget;
+    QGroupBox *shapeGroup;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout1;
+    QHBoxLayout *hboxLayout2;
+    QLabel *typeLabel;
+    QComboBox *typeComboBox;
+    QSpacerItem *spacerItem;
+    QStackedWidget *stackedWidget;
+    QWidget *domePage;
+    QHBoxLayout *hboxLayout3;
+    QVBoxLayout *vboxLayout2;
+    QHBoxLayout *hboxLayout4;
+    QLabel *domeRadiusLabel;
+    QLineEdit *domeRadiusEdit;
+    QHBoxLayout *hboxLayout5;
+    QLabel *domeAzimResLabel;
+    QSpinBox *domeAzimResSpinBox;
+    QHBoxLayout *hboxLayout6;
+    QLabel *domeElevResLabel;
+    QSpinBox *domeElevResSpinBox;
+    QHBoxLayout *hboxLayout7;
+    QLabel *domeSubdivLabel;
+    QSpinBox *domeSubdivSpinBox;
+    QCheckBox *domeFullDomeCheckBox;
+    QSpacerItem *spacerItem1;
+    QWidget *planePage;
+    QHBoxLayout *hboxLayout8;
+    QVBoxLayout *vboxLayout3;
+    QGridLayout *gridLayout;
+    QLabel *planeHeightLabel;
+    QLabel *planeHorResLabel;
+    QSpinBox *planeHorResSpinBox;
+    QLabel *planeVertResLabel;
+    QLineEdit *planeWidthEdit;
+    QLabel *planeWidthLabel;
+    QLineEdit *planeHeightEdit;
+    QSpinBox *planeVertResSpinBox;
+    QSpacerItem *spacerItem2;
+    QWidget *boxPage;
+    QHBoxLayout *hboxLayout9;
+    QVBoxLayout *vboxLayout4;
+    QGridLayout *gridLayout1;
+    QSpinBox *boxVertResSpinBox;
+    QLabel *boxHorResLabel;
+    QLabel *boxDepthResLabel;
+    QLabel *boxHeightLabel;
+    QLabel *boxWidthLabel;
+    QLineEdit *boxWidthEdit;
+    QSpinBox *boxHorResSpinBox;
+    QSpinBox *boxDepthResSpinBox;
+    QLabel *boxVertResLabel;
+    QLineEdit *boxDepthEdit;
+    QLabel *boxDepthLabel;
+    QLineEdit *boxHeightEdit;
+    QSpacerItem *spacerItem3;
+    QWidget *modelPage;
+    QHBoxLayout *hboxLayout10;
+    QVBoxLayout *vboxLayout5;
+    QHBoxLayout *hboxLayout11;
+    QLabel *modelFileNameLabel;
+    QLineEdit *modelFileNameEdit;
+    QPushButton *modelBrowseButton;
+    QSpacerItem *spacerItem4;
+    QHBoxLayout *hboxLayout12;
+    QCheckBox *frameCheckBox;
+    QLabel *frameLineWidthLabel;
+    QSpinBox *frameLineWidthSpinBox;
+
+    void setupUi(QWidget *QScreenWidget)
+    {
+        if (QScreenWidget->objectName().isEmpty())
+            QScreenWidget->setObjectName(QString::fromUtf8("QScreenWidget"));
+        QScreenWidget->resize(183, 222);
+        hboxLayout = new QHBoxLayout(QScreenWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(4);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        transformWidget = new projection::QTransformMatrixWidget(QScreenWidget);
+        transformWidget->setObjectName(QString::fromUtf8("transformWidget"));
+        transformWidget->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout->addWidget(transformWidget);
+
+        shapeGroup = new QGroupBox(QScreenWidget);
+        shapeGroup->setObjectName(QString::fromUtf8("shapeGroup"));
+        hboxLayout1 = new QHBoxLayout(shapeGroup);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout1 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout1->setMargin(0);
+#endif
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout2->setMargin(0);
+#endif
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        typeLabel = new QLabel(shapeGroup);
+        typeLabel->setObjectName(QString::fromUtf8("typeLabel"));
+
+        hboxLayout2->addWidget(typeLabel);
+
+        typeComboBox = new QComboBox(shapeGroup);
+        typeComboBox->setObjectName(QString::fromUtf8("typeComboBox"));
+        typeComboBox->setMinimumSize(QSize(96, 0));
+
+        hboxLayout2->addWidget(typeComboBox);
+
+        spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+        hboxLayout2->addItem(spacerItem);
+
+
+        vboxLayout1->addLayout(hboxLayout2);
+
+        stackedWidget = new QStackedWidget(shapeGroup);
+        stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
+        domePage = new QWidget();
+        domePage->setObjectName(QString::fromUtf8("domePage"));
+        hboxLayout3 = new QHBoxLayout(domePage);
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(4);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        vboxLayout2 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout2->setMargin(0);
+#endif
+        vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout4->setMargin(0);
+#endif
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        domeRadiusLabel = new QLabel(domePage);
+        domeRadiusLabel->setObjectName(QString::fromUtf8("domeRadiusLabel"));
+
+        hboxLayout4->addWidget(domeRadiusLabel);
+
+        domeRadiusEdit = new QLineEdit(domePage);
+        domeRadiusEdit->setObjectName(QString::fromUtf8("domeRadiusEdit"));
+
+        hboxLayout4->addWidget(domeRadiusEdit);
+
+
+        vboxLayout2->addLayout(hboxLayout4);
+
+        hboxLayout5 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout5->setSpacing(6);
+#endif
+        hboxLayout5->setMargin(0);
+        hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
+        domeAzimResLabel = new QLabel(domePage);
+        domeAzimResLabel->setObjectName(QString::fromUtf8("domeAzimResLabel"));
+
+        hboxLayout5->addWidget(domeAzimResLabel);
+
+        domeAzimResSpinBox = new QSpinBox(domePage);
+        domeAzimResSpinBox->setObjectName(QString::fromUtf8("domeAzimResSpinBox"));
+        domeAzimResSpinBox->setMaximum(128);
+        domeAzimResSpinBox->setMinimum(2);
+
+        hboxLayout5->addWidget(domeAzimResSpinBox);
+
+
+        vboxLayout2->addLayout(hboxLayout5);
+
+        hboxLayout6 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout6->setSpacing(6);
+#endif
+        hboxLayout6->setMargin(0);
+        hboxLayout6->setObjectName(QString::fromUtf8("hboxLayout6"));
+        domeElevResLabel = new QLabel(domePage);
+        domeElevResLabel->setObjectName(QString::fromUtf8("domeElevResLabel"));
+
+        hboxLayout6->addWidget(domeElevResLabel);
+
+        domeElevResSpinBox = new QSpinBox(domePage);
+        domeElevResSpinBox->setObjectName(QString::fromUtf8("domeElevResSpinBox"));
+        domeElevResSpinBox->setMaximum(128);
+        domeElevResSpinBox->setMinimum(2);
+
+        hboxLayout6->addWidget(domeElevResSpinBox);
+
+
+        vboxLayout2->addLayout(hboxLayout6);
+
+        hboxLayout7 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout7->setSpacing(6);
+#endif
+        hboxLayout7->setMargin(0);
+        hboxLayout7->setObjectName(QString::fromUtf8("hboxLayout7"));
+        domeSubdivLabel = new QLabel(domePage);
+        domeSubdivLabel->setObjectName(QString::fromUtf8("domeSubdivLabel"));
+
+        hboxLayout7->addWidget(domeSubdivLabel);
+
+        domeSubdivSpinBox = new QSpinBox(domePage);
+        domeSubdivSpinBox->setObjectName(QString::fromUtf8("domeSubdivSpinBox"));
+        domeSubdivSpinBox->setMaximum(8);
+        domeSubdivSpinBox->setMinimum(1);
+
+        hboxLayout7->addWidget(domeSubdivSpinBox);
+
+
+        vboxLayout2->addLayout(hboxLayout7);
+
+        domeFullDomeCheckBox = new QCheckBox(domePage);
+        domeFullDomeCheckBox->setObjectName(QString::fromUtf8("domeFullDomeCheckBox"));
+
+        vboxLayout2->addWidget(domeFullDomeCheckBox);
+
+        spacerItem1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout2->addItem(spacerItem1);
+
+
+        hboxLayout3->addLayout(vboxLayout2);
+
+        stackedWidget->addWidget(domePage);
+        planePage = new QWidget();
+        planePage->setObjectName(QString::fromUtf8("planePage"));
+        hboxLayout8 = new QHBoxLayout(planePage);
+#ifndef Q_OS_MAC
+        hboxLayout8->setSpacing(6);
+#endif
+        hboxLayout8->setMargin(4);
+        hboxLayout8->setObjectName(QString::fromUtf8("hboxLayout8"));
+        vboxLayout3 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout3->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout3->setMargin(0);
+#endif
+        vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
+        gridLayout = new QGridLayout();
+#ifndef Q_OS_MAC
+        gridLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout->setMargin(0);
+#endif
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        planeHeightLabel = new QLabel(planePage);
+        planeHeightLabel->setObjectName(QString::fromUtf8("planeHeightLabel"));
+
+        gridLayout->addWidget(planeHeightLabel, 1, 0, 1, 1);
+
+        planeHorResLabel = new QLabel(planePage);
+        planeHorResLabel->setObjectName(QString::fromUtf8("planeHorResLabel"));
+
+        gridLayout->addWidget(planeHorResLabel, 0, 2, 1, 1);
+
+        planeHorResSpinBox = new QSpinBox(planePage);
+        planeHorResSpinBox->setObjectName(QString::fromUtf8("planeHorResSpinBox"));
+        planeHorResSpinBox->setMaximum(128);
+        planeHorResSpinBox->setMinimum(1);
+
+        gridLayout->addWidget(planeHorResSpinBox, 0, 3, 1, 1);
+
+        planeVertResLabel = new QLabel(planePage);
+        planeVertResLabel->setObjectName(QString::fromUtf8("planeVertResLabel"));
+
+        gridLayout->addWidget(planeVertResLabel, 1, 2, 1, 1);
+
+        planeWidthEdit = new QLineEdit(planePage);
+        planeWidthEdit->setObjectName(QString::fromUtf8("planeWidthEdit"));
+
+        gridLayout->addWidget(planeWidthEdit, 0, 1, 1, 1);
+
+        planeWidthLabel = new QLabel(planePage);
+        planeWidthLabel->setObjectName(QString::fromUtf8("planeWidthLabel"));
+
+        gridLayout->addWidget(planeWidthLabel, 0, 0, 1, 1);
+
+        planeHeightEdit = new QLineEdit(planePage);
+        planeHeightEdit->setObjectName(QString::fromUtf8("planeHeightEdit"));
+
+        gridLayout->addWidget(planeHeightEdit, 1, 1, 1, 1);
+
+        planeVertResSpinBox = new QSpinBox(planePage);
+        planeVertResSpinBox->setObjectName(QString::fromUtf8("planeVertResSpinBox"));
+        planeVertResSpinBox->setMaximum(128);
+        planeVertResSpinBox->setMinimum(1);
+
+        gridLayout->addWidget(planeVertResSpinBox, 1, 3, 1, 1);
+
+
+        vboxLayout3->addLayout(gridLayout);
+
+        spacerItem2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout3->addItem(spacerItem2);
+
+
+        hboxLayout8->addLayout(vboxLayout3);
+
+        stackedWidget->addWidget(planePage);
+        boxPage = new QWidget();
+        boxPage->setObjectName(QString::fromUtf8("boxPage"));
+        hboxLayout9 = new QHBoxLayout(boxPage);
+#ifndef Q_OS_MAC
+        hboxLayout9->setSpacing(6);
+#endif
+        hboxLayout9->setMargin(4);
+        hboxLayout9->setObjectName(QString::fromUtf8("hboxLayout9"));
+        vboxLayout4 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout4->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout4->setMargin(0);
+#endif
+        vboxLayout4->setObjectName(QString::fromUtf8("vboxLayout4"));
+        gridLayout1 = new QGridLayout();
+#ifndef Q_OS_MAC
+        gridLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout1->setMargin(0);
+#endif
+        gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
+        boxVertResSpinBox = new QSpinBox(boxPage);
+        boxVertResSpinBox->setObjectName(QString::fromUtf8("boxVertResSpinBox"));
+        boxVertResSpinBox->setMaximum(128);
+        boxVertResSpinBox->setMinimum(1);
+
+        gridLayout1->addWidget(boxVertResSpinBox, 1, 3, 1, 1);
+
+        boxHorResLabel = new QLabel(boxPage);
+        boxHorResLabel->setObjectName(QString::fromUtf8("boxHorResLabel"));
+
+        gridLayout1->addWidget(boxHorResLabel, 0, 2, 1, 1);
+
+        boxDepthResLabel = new QLabel(boxPage);
+        boxDepthResLabel->setObjectName(QString::fromUtf8("boxDepthResLabel"));
+
+        gridLayout1->addWidget(boxDepthResLabel, 2, 2, 1, 1);
+
+        boxHeightLabel = new QLabel(boxPage);
+        boxHeightLabel->setObjectName(QString::fromUtf8("boxHeightLabel"));
+
+        gridLayout1->addWidget(boxHeightLabel, 1, 0, 1, 1);
+
+        boxWidthLabel = new QLabel(boxPage);
+        boxWidthLabel->setObjectName(QString::fromUtf8("boxWidthLabel"));
+
+        gridLayout1->addWidget(boxWidthLabel, 0, 0, 1, 1);
+
+        boxWidthEdit = new QLineEdit(boxPage);
+        boxWidthEdit->setObjectName(QString::fromUtf8("boxWidthEdit"));
+
+        gridLayout1->addWidget(boxWidthEdit, 0, 1, 1, 1);
+
+        boxHorResSpinBox = new QSpinBox(boxPage);
+        boxHorResSpinBox->setObjectName(QString::fromUtf8("boxHorResSpinBox"));
+        boxHorResSpinBox->setMaximum(128);
+        boxHorResSpinBox->setMinimum(1);
+
+        gridLayout1->addWidget(boxHorResSpinBox, 0, 3, 1, 1);
+
+        boxDepthResSpinBox = new QSpinBox(boxPage);
+        boxDepthResSpinBox->setObjectName(QString::fromUtf8("boxDepthResSpinBox"));
+        boxDepthResSpinBox->setMaximum(128);
+        boxDepthResSpinBox->setMinimum(1);
+
+        gridLayout1->addWidget(boxDepthResSpinBox, 2, 3, 1, 1);
+
+        boxVertResLabel = new QLabel(boxPage);
+        boxVertResLabel->setObjectName(QString::fromUtf8("boxVertResLabel"));
+
+        gridLayout1->addWidget(boxVertResLabel, 1, 2, 1, 1);
+
+        boxDepthEdit = new QLineEdit(boxPage);
+        boxDepthEdit->setObjectName(QString::fromUtf8("boxDepthEdit"));
+
+        gridLayout1->addWidget(boxDepthEdit, 2, 1, 1, 1);
+
+        boxDepthLabel = new QLabel(boxPage);
+        boxDepthLabel->setObjectName(QString::fromUtf8("boxDepthLabel"));
+
+        gridLayout1->addWidget(boxDepthLabel, 2, 0, 1, 1);
+
+        boxHeightEdit = new QLineEdit(boxPage);
+        boxHeightEdit->setObjectName(QString::fromUtf8("boxHeightEdit"));
+
+        gridLayout1->addWidget(boxHeightEdit, 1, 1, 1, 1);
+
+
+        vboxLayout4->addLayout(gridLayout1);
+
+        spacerItem3 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout4->addItem(spacerItem3);
+
+
+        hboxLayout9->addLayout(vboxLayout4);
+
+        stackedWidget->addWidget(boxPage);
+        modelPage = new QWidget();
+        modelPage->setObjectName(QString::fromUtf8("modelPage"));
+        hboxLayout10 = new QHBoxLayout(modelPage);
+#ifndef Q_OS_MAC
+        hboxLayout10->setSpacing(6);
+#endif
+        hboxLayout10->setMargin(4);
+        hboxLayout10->setObjectName(QString::fromUtf8("hboxLayout10"));
+        vboxLayout5 = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout5->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout5->setMargin(0);
+#endif
+        vboxLayout5->setObjectName(QString::fromUtf8("vboxLayout5"));
+        hboxLayout11 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout11->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout11->setMargin(0);
+#endif
+        hboxLayout11->setObjectName(QString::fromUtf8("hboxLayout11"));
+        modelFileNameLabel = new QLabel(modelPage);
+        modelFileNameLabel->setObjectName(QString::fromUtf8("modelFileNameLabel"));
+
+        hboxLayout11->addWidget(modelFileNameLabel);
+
+        modelFileNameEdit = new QLineEdit(modelPage);
+        modelFileNameEdit->setObjectName(QString::fromUtf8("modelFileNameEdit"));
+
+        hboxLayout11->addWidget(modelFileNameEdit);
+
+        modelBrowseButton = new QPushButton(modelPage);
+        modelBrowseButton->setObjectName(QString::fromUtf8("modelBrowseButton"));
+        QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(0));
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(modelBrowseButton->sizePolicy().hasHeightForWidth());
+        modelBrowseButton->setSizePolicy(sizePolicy);
+        modelBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        hboxLayout11->addWidget(modelBrowseButton);
+
+
+        vboxLayout5->addLayout(hboxLayout11);
+
+        spacerItem4 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout5->addItem(spacerItem4);
+
+
+        hboxLayout10->addLayout(vboxLayout5);
+
+        stackedWidget->addWidget(modelPage);
+
+        vboxLayout1->addWidget(stackedWidget);
+
+
+        hboxLayout1->addLayout(vboxLayout1);
+
+
+        vboxLayout->addWidget(shapeGroup);
+
+        hboxLayout12 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout12->setSpacing(6);
+#endif
+        hboxLayout12->setMargin(0);
+        hboxLayout12->setObjectName(QString::fromUtf8("hboxLayout12"));
+        frameCheckBox = new QCheckBox(QScreenWidget);
+        frameCheckBox->setObjectName(QString::fromUtf8("frameCheckBox"));
+
+        hboxLayout12->addWidget(frameCheckBox);
+
+        frameLineWidthLabel = new QLabel(QScreenWidget);
+        frameLineWidthLabel->setObjectName(QString::fromUtf8("frameLineWidthLabel"));
+
+        hboxLayout12->addWidget(frameLineWidthLabel);
+
+        frameLineWidthSpinBox = new QSpinBox(QScreenWidget);
+        frameLineWidthSpinBox->setObjectName(QString::fromUtf8("frameLineWidthSpinBox"));
+        frameLineWidthSpinBox->setMaximum(4);
+        frameLineWidthSpinBox->setMinimum(1);
+
+        hboxLayout12->addWidget(frameLineWidthSpinBox);
+
+
+        vboxLayout->addLayout(hboxLayout12);
+
+
+        hboxLayout->addLayout(vboxLayout);
+
+        QWidget::setTabOrder(typeComboBox, transformWidget);
+        QWidget::setTabOrder(transformWidget, domeRadiusEdit);
+        QWidget::setTabOrder(domeRadiusEdit, domeAzimResSpinBox);
+        QWidget::setTabOrder(domeAzimResSpinBox, domeElevResSpinBox);
+        QWidget::setTabOrder(domeElevResSpinBox, domeFullDomeCheckBox);
+        QWidget::setTabOrder(domeFullDomeCheckBox, planeWidthEdit);
+        QWidget::setTabOrder(planeWidthEdit, planeHeightEdit);
+        QWidget::setTabOrder(planeHeightEdit, planeHorResSpinBox);
+        QWidget::setTabOrder(planeHorResSpinBox, planeVertResSpinBox);
+        QWidget::setTabOrder(planeVertResSpinBox, boxWidthEdit);
+        QWidget::setTabOrder(boxWidthEdit, boxHeightEdit);
+        QWidget::setTabOrder(boxHeightEdit, boxDepthEdit);
+        QWidget::setTabOrder(boxDepthEdit, boxHorResSpinBox);
+        QWidget::setTabOrder(boxHorResSpinBox, boxVertResSpinBox);
+        QWidget::setTabOrder(boxVertResSpinBox, boxDepthResSpinBox);
+
+        retranslateUi(QScreenWidget);
+
+        stackedWidget->setCurrentIndex(0);
+
+
+        QMetaObject::connectSlotsByName(QScreenWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QScreenWidget)
+    {
+        QScreenWidget->setWindowTitle(QApplication::translate("QScreenWidget", "Screen Settings", 0, QApplication::UnicodeUTF8));
+        shapeGroup->setTitle(QApplication::translate("QScreenWidget", "Shape", 0, QApplication::UnicodeUTF8));
+        typeLabel->setText(QApplication::translate("QScreenWidget", "Type", 0, QApplication::UnicodeUTF8));
+        typeComboBox->clear();
+        typeComboBox->insertItems(0, QStringList()
+         << QApplication::translate("QScreenWidget", "Dome", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QScreenWidget", "Plane", 0, QApplication::UnicodeUTF8)
+         << QApplication::translate("QScreenWidget", "Box", 0, QApplication::UnicodeUTF8)
+        );
+        domeRadiusLabel->setText(QApplication::translate("QScreenWidget", "Radius", 0, QApplication::UnicodeUTF8));
+        domeAzimResLabel->setText(QApplication::translate("QScreenWidget", "Azimuth Res.", 0, QApplication::UnicodeUTF8));
+        domeElevResLabel->setText(QApplication::translate("QScreenWidget", "Elevation Res.", 0, QApplication::UnicodeUTF8));
+        domeSubdivLabel->setText(QApplication::translate("QScreenWidget", "Subdivision", 0, QApplication::UnicodeUTF8));
+        domeFullDomeCheckBox->setText(QApplication::translate("QScreenWidget", "Full dome", 0, QApplication::UnicodeUTF8));
+        planeHeightLabel->setText(QApplication::translate("QScreenWidget", "Height", 0, QApplication::UnicodeUTF8));
+        planeHorResLabel->setText(QApplication::translate("QScreenWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        planeVertResLabel->setText(QApplication::translate("QScreenWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        planeWidthLabel->setText(QApplication::translate("QScreenWidget", "Width", 0, QApplication::UnicodeUTF8));
+        boxHorResLabel->setText(QApplication::translate("QScreenWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        boxDepthResLabel->setText(QApplication::translate("QScreenWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        boxHeightLabel->setText(QApplication::translate("QScreenWidget", "Height", 0, QApplication::UnicodeUTF8));
+        boxWidthLabel->setText(QApplication::translate("QScreenWidget", "Width", 0, QApplication::UnicodeUTF8));
+        boxVertResLabel->setText(QApplication::translate("QScreenWidget", "Res.", 0, QApplication::UnicodeUTF8));
+        boxDepthLabel->setText(QApplication::translate("QScreenWidget", "Depth", 0, QApplication::UnicodeUTF8));
+        modelFileNameLabel->setText(QApplication::translate("QScreenWidget", "File", 0, QApplication::UnicodeUTF8));
+        modelBrowseButton->setText(QApplication::translate("QScreenWidget", "...", 0, QApplication::UnicodeUTF8));
+        frameCheckBox->setText(QApplication::translate("QScreenWidget", "Wireframe", 0, QApplication::UnicodeUTF8));
+        frameLineWidthLabel->setText(QApplication::translate("QScreenWidget", "Width", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QScreenWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QScreenWidget: public Ui_QScreenWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QSCREENWIDGET_H
Index: projectionDesigner/trunk/projdesigner/ui_qsetupdialog.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qsetupdialog.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qsetupdialog.h	(revision 4)
@@ -0,0 +1,184 @@
+/********************************************************************************
+** Form generated from reading ui file 'qsetupdialog.ui'
+**
+** Created: Mon 27. Apr 14:26:16 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QSETUPDIALOG_H
+#define UI_QSETUPDIALOG_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QTabWidget>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+#include "gui/QChannelManagerWidget.h"
+#include "gui/QChannelWidget.h"
+#include "gui/QSceneWidget.h"
+#include "gui/QScreenWidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QSetupDialog
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QTabWidget *tabWidget;
+    QWidget *channelsTab;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout;
+    projection::QChannelManagerWidget *channelManager;
+    QGroupBox *channelGroup;
+    QHBoxLayout *hboxLayout2;
+    projection::QChannelWidget *channel;
+    QSpacerItem *spacerItem;
+    QWidget *screenTab;
+    QVBoxLayout *vboxLayout1;
+    projection::QScreenWidget *screen;
+    QSpacerItem *spacerItem1;
+    QWidget *sceneTab;
+    QVBoxLayout *vboxLayout2;
+    projection::QSceneWidget *scene;
+    QSpacerItem *spacerItem2;
+
+    void setupUi(QWidget *QSetupDialog)
+    {
+        if (QSetupDialog->objectName().isEmpty())
+            QSetupDialog->setObjectName(QString::fromUtf8("QSetupDialog"));
+        QSetupDialog->resize(196, 356);
+        hboxLayout = new QHBoxLayout(QSetupDialog);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        tabWidget = new QTabWidget(QSetupDialog);
+        tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
+        channelsTab = new QWidget();
+        channelsTab->setObjectName(QString::fromUtf8("channelsTab"));
+        hboxLayout1 = new QHBoxLayout(channelsTab);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(4);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        channelManager = new projection::QChannelManagerWidget(channelsTab);
+        channelManager->setObjectName(QString::fromUtf8("channelManager"));
+        channelManager->setMaximumSize(QSize(16777215, 120));
+        channelManager->setFocusPolicy(Qt::StrongFocus);
+
+        vboxLayout->addWidget(channelManager);
+
+        channelGroup = new QGroupBox(channelsTab);
+        channelGroup->setObjectName(QString::fromUtf8("channelGroup"));
+        QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(1);
+        sizePolicy.setHeightForWidth(channelGroup->sizePolicy().hasHeightForWidth());
+        channelGroup->setSizePolicy(sizePolicy);
+        hboxLayout2 = new QHBoxLayout(channelGroup);
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+        hboxLayout2->setMargin(4);
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        channel = new projection::QChannelWidget(channelGroup);
+        channel->setObjectName(QString::fromUtf8("channel"));
+        channel->setFocusPolicy(Qt::StrongFocus);
+
+        hboxLayout2->addWidget(channel);
+
+
+        vboxLayout->addWidget(channelGroup);
+
+        spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout->addItem(spacerItem);
+
+
+        hboxLayout1->addLayout(vboxLayout);
+
+        tabWidget->addTab(channelsTab, QString());
+        screenTab = new QWidget();
+        screenTab->setObjectName(QString::fromUtf8("screenTab"));
+        vboxLayout1 = new QVBoxLayout(screenTab);
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+        vboxLayout1->setMargin(0);
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        screen = new projection::QScreenWidget(screenTab);
+        screen->setObjectName(QString::fromUtf8("screen"));
+
+        vboxLayout1->addWidget(screen);
+
+        spacerItem1 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout1->addItem(spacerItem1);
+
+        tabWidget->addTab(screenTab, QString());
+        sceneTab = new QWidget();
+        sceneTab->setObjectName(QString::fromUtf8("sceneTab"));
+        vboxLayout2 = new QVBoxLayout(sceneTab);
+#ifndef Q_OS_MAC
+        vboxLayout2->setSpacing(6);
+#endif
+        vboxLayout2->setMargin(0);
+        vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+        scene = new projection::QSceneWidget(sceneTab);
+        scene->setObjectName(QString::fromUtf8("scene"));
+
+        vboxLayout2->addWidget(scene);
+
+        spacerItem2 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout2->addItem(spacerItem2);
+
+        tabWidget->addTab(sceneTab, QString());
+
+        hboxLayout->addWidget(tabWidget);
+
+        QWidget::setTabOrder(channelManager, channel);
+        QWidget::setTabOrder(channel, tabWidget);
+
+        retranslateUi(QSetupDialog);
+
+        QMetaObject::connectSlotsByName(QSetupDialog);
+    } // setupUi
+
+    void retranslateUi(QWidget *QSetupDialog)
+    {
+        QSetupDialog->setWindowTitle(QApplication::translate("QSetupDialog", "Multichannel Projection Designer", 0, QApplication::UnicodeUTF8));
+        channelGroup->setTitle(QApplication::translate("QSetupDialog", "Channel", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(channelsTab), QApplication::translate("QSetupDialog", "Channels", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(screenTab), QApplication::translate("QSetupDialog", "Screen", 0, QApplication::UnicodeUTF8));
+        tabWidget->setTabText(tabWidget->indexOf(sceneTab), QApplication::translate("QSetupDialog", "Scene", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QSetupDialog);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QSetupDialog: public Ui_QSetupDialog {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QSETUPDIALOG_H
Index: projectionDesigner/trunk/projdesigner/ui_qtransformmatrixwidget.h
===================================================================
--- projectionDesigner/trunk/projdesigner/ui_qtransformmatrixwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesigner/ui_qtransformmatrixwidget.h	(revision 4)
@@ -0,0 +1,167 @@
+/********************************************************************************
+** Form generated from reading ui file 'qtransformmatrixwidget.ui'
+**
+** Created: Mon 27. Apr 14:25:23 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_QTRANSFORMMATRIXWIDGET_H
+#define UI_QTRANSFORMMATRIXWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_QTransformMatrixWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QGroupBox *transformGroup;
+    QHBoxLayout *hboxLayout1;
+    QGridLayout *gridLayout;
+    QLineEdit *posZEdit;
+    QLineEdit *rotHEdit;
+    QLabel *posLabel;
+    QLabel *rotLabel;
+    QLineEdit *posXEdit;
+    QLineEdit *rotREdit;
+    QLineEdit *rotPEdit;
+    QLineEdit *posYEdit;
+    QLabel *scaleLabel;
+    QLineEdit *scaleXEdit;
+    QLineEdit *scaleYEdit;
+    QLineEdit *scaleZEdit;
+
+    void setupUi(QWidget *QTransformMatrixWidget)
+    {
+        if (QTransformMatrixWidget->objectName().isEmpty())
+            QTransformMatrixWidget->setObjectName(QString::fromUtf8("QTransformMatrixWidget"));
+        QTransformMatrixWidget->resize(179, 78);
+        hboxLayout = new QHBoxLayout(QTransformMatrixWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        transformGroup = new QGroupBox(QTransformMatrixWidget);
+        transformGroup->setObjectName(QString::fromUtf8("transformGroup"));
+        hboxLayout1 = new QHBoxLayout(transformGroup);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(0);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        gridLayout = new QGridLayout();
+#ifndef Q_OS_MAC
+        gridLayout->setSpacing(6);
+#endif
+        gridLayout->setMargin(4);
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        posZEdit = new QLineEdit(transformGroup);
+        posZEdit->setObjectName(QString::fromUtf8("posZEdit"));
+
+        gridLayout->addWidget(posZEdit, 0, 3, 1, 1);
+
+        rotHEdit = new QLineEdit(transformGroup);
+        rotHEdit->setObjectName(QString::fromUtf8("rotHEdit"));
+
+        gridLayout->addWidget(rotHEdit, 1, 1, 1, 1);
+
+        posLabel = new QLabel(transformGroup);
+        posLabel->setObjectName(QString::fromUtf8("posLabel"));
+
+        gridLayout->addWidget(posLabel, 0, 0, 1, 1);
+
+        rotLabel = new QLabel(transformGroup);
+        rotLabel->setObjectName(QString::fromUtf8("rotLabel"));
+
+        gridLayout->addWidget(rotLabel, 1, 0, 1, 1);
+
+        posXEdit = new QLineEdit(transformGroup);
+        posXEdit->setObjectName(QString::fromUtf8("posXEdit"));
+
+        gridLayout->addWidget(posXEdit, 0, 1, 1, 1);
+
+        rotREdit = new QLineEdit(transformGroup);
+        rotREdit->setObjectName(QString::fromUtf8("rotREdit"));
+
+        gridLayout->addWidget(rotREdit, 1, 3, 1, 1);
+
+        rotPEdit = new QLineEdit(transformGroup);
+        rotPEdit->setObjectName(QString::fromUtf8("rotPEdit"));
+
+        gridLayout->addWidget(rotPEdit, 1, 2, 1, 1);
+
+        posYEdit = new QLineEdit(transformGroup);
+        posYEdit->setObjectName(QString::fromUtf8("posYEdit"));
+
+        gridLayout->addWidget(posYEdit, 0, 2, 1, 1);
+
+        scaleLabel = new QLabel(transformGroup);
+        scaleLabel->setObjectName(QString::fromUtf8("scaleLabel"));
+
+        gridLayout->addWidget(scaleLabel, 2, 0, 1, 1);
+
+        scaleXEdit = new QLineEdit(transformGroup);
+        scaleXEdit->setObjectName(QString::fromUtf8("scaleXEdit"));
+
+        gridLayout->addWidget(scaleXEdit, 2, 1, 1, 1);
+
+        scaleYEdit = new QLineEdit(transformGroup);
+        scaleYEdit->setObjectName(QString::fromUtf8("scaleYEdit"));
+
+        gridLayout->addWidget(scaleYEdit, 2, 2, 1, 1);
+
+        scaleZEdit = new QLineEdit(transformGroup);
+        scaleZEdit->setObjectName(QString::fromUtf8("scaleZEdit"));
+
+        gridLayout->addWidget(scaleZEdit, 2, 3, 1, 1);
+
+
+        hboxLayout1->addLayout(gridLayout);
+
+
+        hboxLayout->addWidget(transformGroup);
+
+        QWidget::setTabOrder(posXEdit, posYEdit);
+        QWidget::setTabOrder(posYEdit, posZEdit);
+        QWidget::setTabOrder(posZEdit, rotHEdit);
+        QWidget::setTabOrder(rotHEdit, rotPEdit);
+        QWidget::setTabOrder(rotPEdit, rotREdit);
+
+        retranslateUi(QTransformMatrixWidget);
+
+        QMetaObject::connectSlotsByName(QTransformMatrixWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *QTransformMatrixWidget)
+    {
+        QTransformMatrixWidget->setWindowTitle(QApplication::translate("QTransformMatrixWidget", "Matrix Settings", 0, QApplication::UnicodeUTF8));
+        transformGroup->setTitle(QApplication::translate("QTransformMatrixWidget", "Transform", 0, QApplication::UnicodeUTF8));
+        posLabel->setText(QApplication::translate("QTransformMatrixWidget", "Pos", 0, QApplication::UnicodeUTF8));
+        rotLabel->setText(QApplication::translate("QTransformMatrixWidget", "Rot", 0, QApplication::UnicodeUTF8));
+        scaleLabel->setText(QApplication::translate("QTransformMatrixWidget", "Scale", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(QTransformMatrixWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class QTransformMatrixWidget: public Ui_QTransformMatrixWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_QTRANSFORMMATRIXWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.cpp	(revision 4)
@@ -0,0 +1,258 @@
+#include "DefaultCubemapSceneContent.h"
+
+
+const QString DefaultCubemapSceneContent::g_scene_name=QObject::tr("Cubemap");
+
+
+
+/**
+ * Default constructor
+ *
+ */
+DefaultCubemapSceneContent::DefaultCubemapSceneContent(SceneInterface* plugin):
+    SceneContent(plugin)
+{
+    for (unsigned int i=0; i<6; ++i)
+        m_textureIndex[i] = 0;
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultCubemapSceneContent::~DefaultCubemapSceneContent()
+{
+    for (unsigned int i=0; i<6; ++i)
+        if (glIsTexture(m_textureIndex[i]))
+            glDeleteTextures(1, &m_textureIndex[i]);
+}
+
+
+/**
+ * Implements the copy from other contents.
+ *
+ * This method is used by the copy constructor.
+ *
+ * @param content The source content to copy from.
+ *
+ * @return true if the copy is ok, false otherwise. The copy can fail if
+ *         SceneContent is not a DefaultCubemapSceneContent.
+ *
+ * @seealso is_equal_to
+ *
+ */
+bool DefaultCubemapSceneContent::copy_from(const SceneContent& data) 
+{
+    if (!SceneContent::copy_from(data)) return false;
+    Q_ASSERT(NULL!=plugin());
+    Q_ASSERT(NULL!=data.plugin());
+    const DefaultCubemapSceneContent& _data = static_cast<const DefaultCubemapSceneContent&>(data);
+    setTexture (CUBEMAP_FACE_FRONT,  _data.getTexture(CUBEMAP_FACE_FRONT));
+    setTexture (CUBEMAP_FACE_BACK,   _data.getTexture(CUBEMAP_FACE_BACK));
+    setTexture (CUBEMAP_FACE_LEFT,   _data.getTexture(CUBEMAP_FACE_LEFT));
+    setTexture (CUBEMAP_FACE_RIGHT,  _data.getTexture(CUBEMAP_FACE_RIGHT));
+    setTexture (CUBEMAP_FACE_TOP,    _data.getTexture(CUBEMAP_FACE_TOP));
+    setTexture (CUBEMAP_FACE_BOTTOM, _data.getTexture(CUBEMAP_FACE_BOTTOM));
+    return true;
+}
+
+
+/**
+ * Implements the egality-test with other contents.
+ *
+ * This could be an operator==.
+ *
+ * @param content The content to compare with.
+ *
+ * @return true if the content are equal, false otherwise. The test can
+ *         fail if the contents have different parameters, but also it
+ *         SceneContent is not a DefaultCubemapSceneContent.
+ *
+ * @seealso copy_from
+ *
+ */
+bool DefaultCubemapSceneContent::is_equal_to(const SceneContent& data) const
+{
+    if (!SceneContent::is_equal_to(data)) return false;
+    const DefaultCubemapSceneContent& _data = static_cast<const DefaultCubemapSceneContent&>(data);
+    return getTexture(CUBEMAP_FACE_FRONT) ==_data.getTexture(CUBEMAP_FACE_FRONT)
+	&& getTexture(CUBEMAP_FACE_BACK)  ==_data.getTexture(CUBEMAP_FACE_BACK)
+	&& getTexture(CUBEMAP_FACE_LEFT)  ==_data.getTexture(CUBEMAP_FACE_LEFT)
+	&& getTexture(CUBEMAP_FACE_RIGHT) ==_data.getTexture(CUBEMAP_FACE_RIGHT)
+	&& getTexture(CUBEMAP_FACE_TOP)   ==_data.getTexture(CUBEMAP_FACE_TOP)
+	&& getTexture(CUBEMAP_FACE_BOTTOM)==_data.getTexture(CUBEMAP_FACE_BOTTOM);
+}
+
+
+/**
+ * Draws the cubemap.
+ *
+ * @param glWidget The QGLWidget that own the OpenGL context.
+ * @param cameraMatrix The camera matrix that must be use.
+ *
+ */
+void DefaultCubemapSceneContent::draw(QGLWidget* glWidget, const float* cameraMatrix)
+{
+    Q_UNUSED(cameraMatrix);
+    glPushMatrix();
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+    glEnable(GL_TEXTURE_2D);
+    glDisable(GL_LIGHTING);
+
+    for (unsigned int i=0; i<6; ++i) {
+        if (!glIsTexture(m_textureIndex[i]) && !m_textureFileNames[i].isEmpty())
+        {
+            m_textureIndex[i] = glWidget->bindTexture(m_textureFileNames[i]);
+        }
+    }
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_FRONT]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f(-SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f( SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f(-SIZE,  SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f( SIZE,  SIZE, -SIZE);
+    glEnd();
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_BACK]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f(-SIZE, -SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f(-SIZE,  SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f( SIZE, -SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f( SIZE,  SIZE,  SIZE);
+    glEnd();
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_LEFT]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f(-SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f(-SIZE, -SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f(-SIZE,  SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f(-SIZE,  SIZE,  SIZE);
+    glEnd();
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_RIGHT]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f( SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f( SIZE,  SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f( SIZE, -SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f( SIZE,  SIZE,  SIZE);
+    glEnd();
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_TOP]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f(-SIZE,  SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f( SIZE,  SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f(-SIZE,  SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f( SIZE,  SIZE,  SIZE);
+    glEnd();
+
+    glBindTexture(GL_TEXTURE_2D, m_textureIndex[(int)CUBEMAP_FACE_BOTTOM]);
+    glBegin(GL_TRIANGLE_STRIP);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MIN); glVertex3f(-SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MIN, TEXCOORD_MAX); glVertex3f(-SIZE, -SIZE,  SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MIN); glVertex3f( SIZE, -SIZE, -SIZE);
+    glTexCoord2f(TEXCOORD_MAX, TEXCOORD_MAX); glVertex3f( SIZE, -SIZE,  SIZE);
+    glEnd();
+
+    glPopAttrib();
+
+    glPopMatrix();
+}
+
+
+/**
+ * Sets the name of the texture for a face of the cubemap.
+ *
+ * @param face The face of which we want to set the name of the texture.
+ * @param fileName The new name of the texture.
+ *
+ */
+void DefaultCubemapSceneContent::setTexture(CUBEMAP_FACE face, const QString& fileName)
+{
+    if ((int)face < 0 || (int)face > 5) return;
+    if (m_textureFileNames[(int)face] == fileName) return;
+
+    if (glIsTexture(m_textureIndex[(int)face]))
+        glDeleteTextures(1, &m_textureIndex[(int)face]);
+    m_textureIndex[(int)face] = 0;
+    m_textureFileNames[(int)face] = fileName;
+}
+
+
+/**
+ * Gets the name of the texture for a face.
+ *
+ * @param face The face of which we want to know the name of the texture.
+ *
+ * @return A QString with the name of the texture.
+ *
+ */
+QString DefaultCubemapSceneContent::getTexture(CUBEMAP_FACE face) const
+{
+    if ((int)face < 0 || (int)face > 5) return QString::null;
+    return m_textureFileNames[(int)face];
+}
+
+
+/**
+ * Loads the cubemap from a QDomElement.
+ *
+ * @param element The QDomElement to read from.
+ *
+ */
+void DefaultCubemapSceneContent::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+	SceneContent::initFromDOMElement(element);
+        QDomElement texture = element.firstChildElement("texture");
+        while (!texture.isNull())
+        {
+            if (texture.attribute("face") == "front")
+                setTexture(CUBEMAP_FACE_FRONT, texture.attribute("fileName"));
+            else if (texture.attribute("face") == "back")
+                setTexture(CUBEMAP_FACE_BACK, texture.attribute("fileName"));
+            else if (texture.attribute("face") == "left")
+                setTexture(CUBEMAP_FACE_LEFT, texture.attribute("fileName"));
+            else if (texture.attribute("face") == "right")
+                setTexture(CUBEMAP_FACE_RIGHT, texture.attribute("fileName"));
+            else if (texture.attribute("face") == "top")
+                setTexture(CUBEMAP_FACE_TOP, texture.attribute("fileName"));
+            else if (texture.attribute("face") == "bottom")
+                setTexture(CUBEMAP_FACE_BOTTOM, texture.attribute("fileName"));
+            texture = texture.nextSiblingElement("texture");
+        }
+    }
+}
+
+
+/**
+ * Writes the cubemap in a QDomDocument.
+ *
+ * @param name The name of the element.
+ * @param doc The document whom belongs the element.
+ *
+ * @return The QDomElement to add.
+ *
+ */
+QDomElement DefaultCubemapSceneContent::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = SceneContent::domElement(name, doc);
+    for (unsigned int i=0; i<6; ++i)
+    {
+        QDomElement texture = doc.createElement("texture");
+        switch (i) {
+            case 0: texture.setAttribute("face", "front"); break;
+            case 1: texture.setAttribute("face", "back"); break;
+            case 2: texture.setAttribute("face", "left"); break;
+            case 3: texture.setAttribute("face", "right"); break;
+            case 4: texture.setAttribute("face", "top"); break;
+            case 5: texture.setAttribute("face", "bottom"); break;
+        }
+        texture.setAttribute("fileName", m_textureFileNames[i]);
+        de.appendChild(texture);
+    }
+    return de;
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneContent.h	(revision 4)
@@ -0,0 +1,187 @@
+#ifndef __DEFAULT_CUBEMAP_SCENE_CONTENT_H__
+#define __DEFAULT_CUBEMAP_SCENE_CONTENT_H__
+
+
+// Includes system headers
+#include <QtOpenGL>
+#include <stdlib.h>
+#include <GL/glut.h>
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Some defines, first...
+#define SIZE 1.0f
+#define TEXCOORD_MIN 0.001f
+#define TEXCOORD_MAX 0.999f
+
+//! Cube map faces.
+enum CUBEMAP_FACE
+{
+    CUBEMAP_FACE_FRONT=0,   //!< Front face.
+    CUBEMAP_FACE_BACK,      //!< Back face.
+    CUBEMAP_FACE_LEFT,      //!< Left face.
+    CUBEMAP_FACE_RIGHT,     //!< Right face.
+    CUBEMAP_FACE_TOP,       //!< Top face.
+    CUBEMAP_FACE_BOTTOM     //!< Bottom face.
+};
+
+
+/**
+ * Implementation of the class.
+ *
+ * The purpose of the cubemap scene is to create a environment using images all
+ * around the scene.
+ *
+ */
+class DefaultCubemapSceneContent: public SceneContent
+{
+
+public:
+
+
+    /**
+     * Default constructor
+     *
+     */
+    DefaultCubemapSceneContent (SceneInterface* plugin);
+
+
+    /**
+     * Copy constructor.
+     *
+     * Uses copy_from() to make the copy.
+     *
+     */
+    DefaultCubemapSceneContent (const DefaultCubemapSceneContent& data): SceneContent(data) {copy_from(data);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultCubemapSceneContent ();
+
+
+    /**
+     * Implements the copy from other contents.
+     *
+     * This method is used by the copy constructor.
+     *
+     * @param content The source content to copy from.
+     *
+     * @return true if the copy is ok, false otherwise. The copy can fail if
+     *         SceneContent is not a DefaultCubemapSceneContent.
+     *
+     * @seealso is_equal_to
+     *
+     */
+    bool copy_from(const SceneContent& data);
+
+
+    /**
+     * Implements the egality-test with other contents.
+     *
+     * This could be an operator==.
+     *
+     * @param content The content to compare with.
+     *
+     * @return true if the content are equal, false otherwise. The test can
+     *         fail if the contents have different parameters, but also it
+     *         SceneContent is not a DefaultCubemapSceneContent.
+     *
+     * @seealso copy_from
+     *
+     */
+    bool is_equal_to(const SceneContent& data) const;
+
+
+    /**
+     * Draws the cubemap.
+     *
+     * @param glWidget The QGLWidget that own the OpenGL context.
+     * @param cameraMatrix The camera matrix that must be use.
+     *
+     */
+    void draw(QGLWidget* glWidget, const float* cameraMatrix);
+
+    /**
+     * Resets the cubemap.
+     *
+     * This is a pure virtual method of SceneContent.
+     *
+     */
+    void reset (void) {}
+
+
+    /**
+     * Sets the name of the texture for a face of the cubemap.
+     *
+     * @param face The face of which we want to set the name of the texture.
+     * @param fileName The new name of the texture.
+     *
+     */
+    void setTexture(CUBEMAP_FACE face, const QString& fileName);
+
+
+    /**
+     * Gets the name of the texture for a face.
+     *
+     * @param face The face of which we want to know the name of the texture.
+     *
+     * @return A QString with the name of the texture.
+     *
+     */
+    QString getTexture(CUBEMAP_FACE face) const;
+
+
+    /**
+     * Loads the cubemap from a QDomElement.
+     *
+     * @param element The QDomElement to read from.
+     *
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+
+    /**
+     * Writes the cubemap in a QDomDocument.
+     *
+     * @param name The name of the element.
+     * @param doc The document whom belongs the element.
+     *
+     * @return The QDomElement to add.
+     *
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+
+    /**
+     * Gets the name of cubemap scene type, stored in g_scene_name.
+     *
+     * @return The name of cubemap scene type, stored in g_scene_name.
+     *
+     */
+    const QString& scene_name(void) const {return g_scene_name;}
+
+
+    /// Public static const scene name.
+    static const QString g_scene_name;
+
+
+private:
+
+
+    /// The 6 textures names.
+    /// One for each face.
+    /// Indices are defined by the enum CUBEMAP_FACE.
+    QString m_textureFileNames[6];
+
+
+    /// The 6 textures indices (one for each face).
+    unsigned int m_textureIndex[6];
+
+};
+
+
+#endif // __DEFAULT_CUBEMAP_SCENE_CONTENT_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.cpp	(revision 4)
@@ -0,0 +1,219 @@
+#include "DefaultCubemapSceneWidget.h"
+
+
+/**
+ * Default constructor.
+ *
+ */
+DefaultCubemapSceneWidget::DefaultCubemapSceneWidget(SceneInterface *plugin, QWidget* pParent, Qt::WFlags flag): SceneWidget(plugin, pParent, flag), m_content(plugin)
+{
+    setupUi (this);
+    updateGUI();
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultCubemapSceneWidget::~DefaultCubemapSceneWidget()
+{
+}
+
+
+/**
+ * Updates the widget.
+ *
+ * This method can be used it two ways: to force a refresh or to update the
+ * data of the widget.
+ *
+ * @param content A const pointer on the contents to be used for the widget.
+ *                This contents will be duplicated in the widget. If content
+ *                is NULL, the current content are used and the refresh is
+ *                forced. If no content are given, NULL is used.
+ *
+ */
+void DefaultCubemapSceneWidget::updateGUI(const SceneContent* _content)
+{
+    if (_content)
+    {
+	const DefaultCubemapSceneContent *content = static_cast<const DefaultCubemapSceneContent*>(_content);
+	Q_ASSERT(NULL!=content); // <-- Assume that the conversion was successful
+	m_content.copy_from(*content);
+    }
+    // From now, we will only use m_content
+    frontFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_FRONT));
+    backFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_BACK));
+    leftFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_LEFT));
+    rightFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_RIGHT));
+    topFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_TOP));
+    bottomFileNameEdit->setText(m_content.getTexture(CUBEMAP_FACE_BOTTOM));
+}
+
+
+/**
+ * [private slot] Called when the "front file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_frontFileNameEdit_editingFinished()
+{
+    if (frontFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_FRONT))
+    {
+	m_content.setTexture(CUBEMAP_FACE_FRONT, frontFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "front file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_frontBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), frontFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        frontFileNameEdit->setText(fileName);
+        on_frontFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the "back file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_backFileNameEdit_editingFinished()
+{
+    if (backFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_BACK))
+    {
+	m_content.setTexture(CUBEMAP_FACE_BACK, backFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "back file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_backBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), backFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        backFileNameEdit->setText(fileName);
+        on_backFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the "left file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_leftFileNameEdit_editingFinished()
+{
+    if (leftFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_LEFT))
+    {
+	m_content.setTexture(CUBEMAP_FACE_LEFT, leftFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "left file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_leftBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), leftFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        leftFileNameEdit->setText(fileName);
+        on_leftFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the "right file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_rightFileNameEdit_editingFinished()
+{
+    if (rightFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_RIGHT))
+    {
+	m_content.setTexture(CUBEMAP_FACE_RIGHT, rightFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "right file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_rightBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), rightFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        rightFileNameEdit->setText(fileName);
+        on_rightFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the "top file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_topFileNameEdit_editingFinished()
+{
+    if (topFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_TOP))
+    {
+	m_content.setTexture(CUBEMAP_FACE_TOP, topFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "top file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_topBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), topFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        topFileNameEdit->setText(fileName);
+        on_topFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the "bottom file" field is edited.
+ *
+ */
+void DefaultCubemapSceneWidget::on_bottomFileNameEdit_editingFinished()
+{
+    if (bottomFileNameEdit->text()!=m_content.getTexture(CUBEMAP_FACE_BOTTOM))
+    {
+	m_content.setTexture(CUBEMAP_FACE_BOTTOM, bottomFileNameEdit->text());
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "bottom file" button is pressed.
+ *
+ */
+void DefaultCubemapSceneWidget::on_bottomBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Choose a file to open"), bottomFileNameEdit->text(), tr("Image files (*.*)"));
+    if (!fileName.isEmpty()) {
+        bottomFileNameEdit->setText(fileName);
+        on_bottomFileNameEdit_editingFinished();
+    }
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultCubemapSceneWidget.h	(revision 4)
@@ -0,0 +1,179 @@
+#ifndef __DEFAULT_CUBEMAP_SCENE_WIDGET_H__
+#define __DEFAULT_CUBEMAP_SCENE_WIDGET_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes the ui_ header
+#include "ui_defaultcubemapscenewidget.h"
+
+// Includes local headers
+#include "DefaultCubemapSceneContent.h"
+
+
+/**
+ * Implementation of the DefaultCubemapSceneWidget class.
+ *
+ * This widget is used in a stacked widget with all the other scenes,
+ * to configure the CubeMap.
+ *
+ */
+class DefaultCubemapSceneWidget : public SceneWidget, private Ui::DefaultCubemapSceneWidget
+{
+    Q_OBJECT
+		
+
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    DefaultCubemapSceneWidget(SceneInterface *plugin, QWidget* pParent=0, Qt::WFlags flag=0);
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultCubemapSceneWidget();
+
+
+    /**
+     * Updates the widget.
+     *
+     * This method can be used it two ways: to force a refresh or to update the
+     * data of the widget.
+     *
+     * @param content A const pointer on the contents to be used for the widget.
+     *                This contents will be duplicated in the widget. If content
+     *                is NULL, the current content are used and the refresh is
+     *                forced. If no content are given, NULL is used.
+     *
+     */
+    void updateGUI(const SceneContent* content=NULL);
+
+
+    /**
+     * Gets the widget contents.
+     *
+     * @return A const reference on the content of the widget.
+     *
+     */
+    const SceneContent& content(void) const {return m_content;}
+
+
+signals:
+
+
+    /**
+     * [signal] Notify that the contents of the widget have changed.
+     *
+     * This signal is emitted each time that a field is changed.
+     *
+     * @param content A const reference on the new contents (the same as 
+     *                returned by the content() method).
+     *
+     */
+    virtual void dataChanged(const SceneContent& content);
+
+
+private slots:
+
+
+    /**
+     * [private slot] Called when the "front file" field is edited.
+     *
+     */
+    void on_frontFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "front file" button is pressed.
+     *
+     */
+    void on_frontBrowseButton_clicked(void);
+
+
+    /**
+     * [private slot] Called when the "back file" field is edited.
+     *
+     */
+    void on_backFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "back file" button is pressed.
+     *
+     */
+    void on_backBrowseButton_clicked(void);
+
+
+    /**
+     * [private slot] Called when the "left file" field is edited.
+     *
+     */
+    void on_leftFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "left file" button is pressed.
+     *
+     */
+    void on_leftBrowseButton_clicked(void);
+
+
+    /**
+     * [private slot] Called when the "right file" field is edited.
+     *
+     */
+    void on_rightFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "right file" button is pressed.
+     *
+     */
+    void on_rightBrowseButton_clicked(void);
+
+
+    /**
+     * [private slot] Called when the "top file" field is edited.
+     *
+     */
+    void on_topFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "top file" button is pressed.
+     *
+     */
+    void on_topBrowseButton_clicked(void);
+
+
+    /**
+     * [private slot] Called when the "bottom file" field is edited.
+     *
+     */
+    void on_bottomFileNameEdit_editingFinished(void);
+
+
+    /**
+     * [private slot] Called when the "bottom file" button is pressed.
+     *
+     */
+    void on_bottomBrowseButton_clicked(void);
+
+
+private:
+
+
+    /// The current DefaultCubemapSceneContent of the widget.
+    DefaultCubemapSceneContent m_content;
+
+
+};
+
+#endif // __DEFAULT_CUBEMAP_SCENE_WIDGET_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.cpp	(revision 4)
@@ -0,0 +1,117 @@
+#include "DefaultEmptySceneContent.h"
+
+
+const QString DefaultEmptySceneContent::g_scene_name=QObject::tr("Empty");
+
+
+/**
+ * Default constructor
+ *
+ */
+DefaultEmptySceneContent::DefaultEmptySceneContent(SceneInterface* plugin):
+    SceneContent(plugin)
+{
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultEmptySceneContent::~DefaultEmptySceneContent()
+{
+}
+
+
+/**
+ * Implements the copy from other contents.
+ *
+ * This method is used by the copy constructor.
+ * For the empty scene contents, it does nothing.
+ *
+ * @param content The source content to copy from.
+ *
+ * @return true if the copy is ok, false otherwise. The copy can fail if
+ *         SceneContent is not a DefaultEmptySceneContent.
+ *
+ * @seealso is_equal_to
+ *
+ */
+bool DefaultEmptySceneContent::copy_from(const SceneContent& data) 
+{
+    if (!SceneContent::copy_from(data)) return false;
+    Q_ASSERT(NULL!=plugin());
+    Q_ASSERT(NULL!=data.plugin());
+    return true;
+}
+
+
+/**
+ * Implements the egality-test with other contents.
+ *
+ * This could be an operator==. For the empty scene content, the test is not
+ * difficult.
+ *
+ * @param content The content to compare with.
+ *
+ * @return true if the content are equal, false otherwise. The test can
+ *         fail if the contents have different parameters, but also it
+ *         SceneContent is not a DefaultEmptySceneContent.
+ *
+ * @seealso copy_from
+ *
+ */
+bool DefaultEmptySceneContent::is_equal_to(const SceneContent& data) const
+{
+    if (!SceneContent::is_equal_to(data)) return false;
+    return true;
+}
+
+
+/**
+ * Draws the empty scene.
+ *
+ * @param glWidget The QGLWidget that own the OpenGL context.
+ * @param cameraMatrix The camera matrix that must be use.
+ *
+ */
+void DefaultEmptySceneContent::draw(QGLWidget *glWidget, const float* cameraMatrix)
+{
+    Q_UNUSED (glWidget);
+    Q_UNUSED(cameraMatrix);
+}
+
+
+/**
+ * Loads the empty scene from a QDomElement.
+ *
+ * This is implemented for convenience, but it does nothing.
+ *
+ * @param element The QDomElement to read from.
+ *
+ */
+void DefaultEmptySceneContent::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+	SceneContent::initFromDOMElement(element);
+    }
+}
+
+
+/**
+ * Writes the empty scene in a QDomDocument.
+ *
+ * This is implemented for convenience, but it does nothing.
+ *
+ * @param name The name of the element.
+ * @param doc The document whom belongs the element.
+ *
+ * @return The QDomElement to add.
+ *
+ */
+QDomElement DefaultEmptySceneContent::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = SceneContent::domElement(name, doc);
+    return de;
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneContent.h	(revision 4)
@@ -0,0 +1,145 @@
+#ifndef __DEFAULT_EMPTY_SCENE_CONTENT_H__
+#define __DEFAULT_EMPTY_SCENE_CONTENT_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+
+/**
+ * This class implements the contents of the empty scene of the default plugin.
+ *
+ * The empty scene enables the user to have nothing in the scene.
+ *
+ */
+class DefaultEmptySceneContent: public SceneContent
+{
+
+
+public:
+
+
+    /**
+     * Default constructor
+     *
+     */
+    DefaultEmptySceneContent (SceneInterface* plugin);
+
+
+    /**
+     * Copy constructor.
+     *
+     * Uses copy_from() to make the copy.
+     *
+     */
+    DefaultEmptySceneContent (const DefaultEmptySceneContent& data): SceneContent(data) {copy_from(data);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultEmptySceneContent ();
+
+
+    /**
+     * Implements the copy from other contents.
+     *
+     * This method is used by the copy constructor.
+     * For the empty scene contents, it does nothing.
+     *
+     * @param content The source content to copy from.
+     *
+     * @return true if the copy is ok, false otherwise. The copy can fail if
+     *         SceneContent is not a DefaultEmptySceneContent.
+     *
+     * @seealso is_equal_to
+     *
+     */
+    bool copy_from(const SceneContent& data);
+
+
+    /**
+     * Implements the egality-test with other contents.
+     *
+     * This could be an operator==. For the empty scene content, the test is not
+     * difficult.
+     *
+     * @param content The content to compare with.
+     *
+     * @return true if the content are equal, false otherwise. The test can
+     *         fail if the contents have different parameters, but also it
+     *         SceneContent is not a DefaultEmptySceneContent.
+     *
+     * @seealso copy_from
+     *
+     */
+    bool is_equal_to(const SceneContent& data) const;
+
+
+    /**
+     * Draws the empty scene.
+     *
+     * @param glWidget The QGLWidget that own the OpenGL context.
+     * @param cameraMatrix The camera matrix that must be use.
+     *
+     */
+    void draw(QGLWidget* glWidget, const float* cameraMatrix);
+
+
+    /**
+     * Resets the teapot.
+     *
+     * This is a pure virtual method of SceneContent.
+     * This one does nothing.
+     *
+     */
+    void reset (void) {}
+
+
+    /**
+     * Loads the empty scene from a QDomElement.
+     *
+     * This is implemented for convenience, but it does nothing.
+     *
+     * @param element The QDomElement to read from.
+     *
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+
+    /**
+     * Writes the empty scene in a QDomDocument.
+     *
+     * This is implemented for convenience, but it does nothing.
+     *
+     * @param name The name of the element.
+     * @param doc The document whom belongs the element.
+     *
+     * @return The QDomElement to add.
+     *
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+
+    /**
+     * Gets the name of empty scene type, stored in g_scene_name.
+     *
+     * @return The name of empty scene type, stored in g_scene_name.
+     *
+     */
+    const QString& scene_name(void) const {return g_scene_name;}
+
+
+    /// Public static const scene name for the empty scene.
+    static const QString g_scene_name;
+
+
+private:
+
+    // No attribute for the empy scene, of course.
+
+};
+
+
+#endif // __DEFAULT_EMPTY_SCENE_CONTENT_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.cpp	(revision 4)
@@ -0,0 +1,38 @@
+#include "DefaultEmptySceneWidget.h"
+
+
+/**
+ * Default constructor.
+ *
+ */
+DefaultEmptySceneWidget::DefaultEmptySceneWidget(SceneInterface *plugin, QWidget* pParent, Qt::WFlags flag): SceneWidget(plugin, pParent, flag), m_content(plugin)
+{
+    setupUi (this);
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultEmptySceneWidget::~DefaultEmptySceneWidget()
+{
+}
+
+
+/**
+ * Updates the widget.
+ *
+ * This method can be used it two ways: to force a refresh or to update the
+ * data of the widget.
+ *
+ * @param content A const pointer on the contents to be used for the widget.
+ *                This contents will be duplicated in the widget. If content
+ *                is NULL, the current content are used and the refresh is
+ *                forced. If no content are given, NULL is used.
+ *
+ */
+void DefaultEmptySceneWidget::updateGUI(const SceneContent* _content)
+{
+    Q_UNUSED(_content);
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultEmptySceneWidget.h	(revision 4)
@@ -0,0 +1,96 @@
+#ifndef __DEFAULT_EMPTY_SCENE_WIDGET_H__
+#define __DEFAULT_EMPTY_SCENE_WIDGET_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes the ui_ header
+#include "ui_defaultemptyscenewidget.h"
+
+// Includes local headers
+#include "DefaultEmptySceneContent.h"
+
+/**
+ * Implementation of the DefaultEmptySceneWidget class.
+ *
+ * This widget is used in a stacked widget with all the other sceneprojectors,
+ * to configure the Empty Scene. As the empty scene as no parameter, this widget
+ * is quite simple: it is empty.
+ *
+ */
+class DefaultEmptySceneWidget : public SceneWidget,
+				private Ui::DefaultEmptySceneWidget
+{
+    Q_OBJECT
+		
+
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    DefaultEmptySceneWidget(SceneInterface *plugin, QWidget* pParent=0, Qt::WFlags flag=0);
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultEmptySceneWidget();
+
+
+    /**
+     * Updates the widget.
+     *
+     * This method can be used it two ways: to force a refresh or to update the
+     * data of the widget.
+     *
+     * @param content A const pointer on the contents to be used for the widget.
+     *                This contents will be duplicated in the widget. If content
+     *                is NULL, the current content are used and the refresh is
+     *                forced. If no content are given, NULL is used.
+     *
+     */
+    void updateGUI(const SceneContent* data=NULL);
+
+
+    /**
+     * Gets the widget contents.
+     *
+     * @return A const reference on the content of the widget.
+     *
+     */
+    const SceneContent& content(void) const {return m_content;}
+
+
+signals:
+
+
+    /**
+     * [signal] Notify that the contents of the widget have changed.
+     *
+     * This signal will never be emited, because there is no control in the
+     * widget. It is only implemented because the 
+     *     void SceneWidget::dataChanged(const SceneContent&)
+     * is a pure virtual signal.
+     *
+     * @param content A const reference on the new contents (the same as 
+     *                returned by the content() method).
+     *
+     */
+    virtual void dataChanged(const SceneContent&);
+
+
+private:
+
+
+    /// The current DefaultEmptySceneContent of the widget.
+    DefaultEmptySceneContent m_content;
+
+
+};
+
+#endif // __DEFAULT_EMPTY_SCENE_WIDGET_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.cpp	(revision 4)
@@ -0,0 +1,171 @@
+#include "DefaultModelSceneContent.h"
+
+
+const QString DefaultModelSceneContent::g_scene_name=QObject::tr("Model");
+
+
+/**
+ * Default constructor
+ *
+ */
+DefaultModelSceneContent::DefaultModelSceneContent(SceneInterface* plugin):
+    SceneContent(plugin),
+    m_backFaceCulling(true),
+    m_smoothing(true),
+    m_pModel(NULL),
+    m_modelIndex(0)
+{
+    setFileName();
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultModelSceneContent::~DefaultModelSceneContent()
+{
+}
+
+
+/**
+ * Implements the copy from other contents.
+ *
+ * This method is used by the copy constructor.
+ *
+ * @param content The source content to copy from.
+ *
+ * @return true if the copy is ok, false otherwise. The copy can fail if
+ *         SceneContent is not a DefaultModelSceneContent.
+ *
+ * @seealso is_equal_to
+ *
+ */
+bool DefaultModelSceneContent::copy_from(const SceneContent& data) 
+{
+    if (!SceneContent::copy_from(data)) return false;
+    Q_ASSERT(NULL!=plugin());
+    Q_ASSERT(NULL!=data.plugin());
+    const DefaultModelSceneContent& _data = static_cast<const DefaultModelSceneContent&>(data);
+    setFileName(_data.fileName());
+    setBackFaceCulling(_data.backFaceCulling());
+    setSmoothing(_data.smoothing());
+    return true;
+}
+
+
+/**
+ * Implements the egality-test with other contents.
+ *
+ * This could be an operator==.
+ *
+ * @param content The content to compare with.
+ *
+ * @return true if the content are equal, false otherwise. The test can
+ *         fail if the contents have different parameters, but also it
+ *         SceneContent is not a DefaultModelSceneContent.
+ *
+ * @seealso copy_from
+ *
+ */
+bool DefaultModelSceneContent::is_equal_to(const SceneContent& data) const
+{
+    if (!SceneContent::is_equal_to(data)) return false;
+    const DefaultModelSceneContent& _data = static_cast<const DefaultModelSceneContent&>(data);
+    return fileName()==_data.fileName()
+	&& backFaceCulling()==_data.backFaceCulling()
+	&& smoothing()==_data.smoothing();
+}
+
+
+/**
+ * Draws the GLM scene.
+ *
+ * @param glWidget The QGLWidget that own the OpenGL context.
+ * @param cameraMatrix The camera matrix that must be use.
+ *
+ */
+void DefaultModelSceneContent::draw(QGLWidget *glWidget, const float* cameraMatrix)
+{
+    Q_UNUSED (glWidget);
+    Q_UNUSED(cameraMatrix);
+    glPushAttrib(GL_ENABLE_BIT);
+    if (m_modelIndex)
+    {
+        if (m_backFaceCulling)
+            glEnable(GL_CULL_FACE);
+        else
+            glDisable(GL_CULL_FACE);
+        glCallList(m_modelIndex);
+    }
+    glPopAttrib();
+}
+
+
+/**
+ * Sets the filename of the GLM scene.
+ *
+ * @param filename The new filename of the GLM scene.
+ *
+ */
+void DefaultModelSceneContent::setFileName(const QString& fileName)
+{
+    if (m_fileName != fileName)
+    {
+        m_fileName = fileName;
+        if (m_pModel)
+            glmDelete(m_pModel);
+        if (glIsList(m_modelIndex))
+            glDeleteLists(m_modelIndex, 1);
+        m_pModel = glmReadOBJ(fileName.toLocal8Bit().data());
+        glmFacetNormals(m_pModel);
+        glmVertexNormals(m_pModel, 89.5f);
+        m_modelIndex = glGenLists(1);
+        glNewList(m_modelIndex, GL_COMPILE);
+        glmDraw(m_pModel, (m_smoothing?GLM_SMOOTH:GLM_FLAT) | GLM_MATERIAL);
+        glEndList();
+    }
+}
+
+
+/**
+ * Loads the GLM scene from a QDomElement.
+ *
+ * Only the contents are loaded. After this, the model is loaded from the
+ * filename. The model is not in the QDomElement.
+ *
+ * @param element The QDomElement to read from.
+ *
+ */
+void DefaultModelSceneContent::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+	setFileName(element.attribute("fileName"));
+	setBackFaceCulling(element.attribute("backFaceCulling").toLower()=="true");
+	setSmoothing(element.attribute("smoothing").toLower()=="true");
+	SceneContent::initFromDOMElement(element);
+    }
+}
+
+
+/**
+ * Writes the contents in a QDomDocument.
+ *
+ * Only the contents are stored in the QDomElement. The model is not stored
+ * in it.
+ *
+ * @param name The name of the element.
+ * @param doc The document whom belongs the element.
+ *
+ * @return The QDomElement to add.
+ *
+ */
+QDomElement DefaultModelSceneContent::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = SceneContent::domElement(name, doc);
+    de.setAttribute("fileName", fileName());
+    de.setAttribute("backFaceCulling", backFaceCulling());
+    de.setAttribute("smoothing", smoothing());
+    return de;
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneContent.h	(revision 4)
@@ -0,0 +1,224 @@
+#ifndef __DEFAULT_MODEL_SCENE_CONTENT_H__
+#define __DEFAULT_MODEL_SCENE_CONTENT_H__
+
+// Includes system headers
+#include <stdlib.h>
+#include <GL/glut.h>
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes local headers
+#include "glm.h"
+
+
+/**
+ * This class implements the contents to load a 3D scene from a OBJ file.
+ *
+ * A scene loaded from an OBJ file will be called a GLM scene.
+ *
+ */
+class DefaultModelSceneContent: public SceneContent
+{
+
+
+public:
+
+
+    /**
+     * Default constructor
+     *
+     */
+    DefaultModelSceneContent (SceneInterface* plugin);
+
+
+    /**
+     * Copy constructor.
+     *
+     * Uses copy_from() to make the copy.
+     *
+     */
+    DefaultModelSceneContent (const DefaultModelSceneContent& data): SceneContent(data) {copy_from(data);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultModelSceneContent ();
+
+
+    /**
+     * Implements the copy from other contents.
+     *
+     * This method is used by the copy constructor.
+     *
+     * @param content The source content to copy from.
+     *
+     * @return true if the copy is ok, false otherwise. The copy can fail if
+     *         SceneContent is not a DefaultModelSceneContent.
+     *
+     * @seealso is_equal_to
+     *
+     */
+    bool copy_from(const SceneContent& data);
+
+
+    /**
+     * Implements the egality-test with other contents.
+     *
+     * This could be an operator==.
+     *
+     * @param content The content to compare with.
+     *
+     * @return true if the content are equal, false otherwise. The test can
+     *         fail if the contents have different parameters, but also it
+     *         SceneContent is not a DefaultModelSceneContent.
+     *
+     * @seealso copy_from
+     *
+     */
+    bool is_equal_to(const SceneContent& data) const;
+
+
+    /**
+     * Draws the GLM scene.
+     *
+     * @param glWidget The QGLWidget that own the OpenGL context.
+     * @param cameraMatrix The camera matrix that must be use.
+     *
+     */
+    void draw(QGLWidget* glWidget, const float* cameraMatrix);
+
+
+    /**
+     * Resets the GLM scene.
+     *
+     * This is a pure virtual method of SceneContent.
+     * This one does nothing.
+     *
+     */
+    void reset (void) {}
+
+
+    /**
+     * Gets the filename of the GLM scene.
+     *
+     * @return The filename of the GLM scene.
+     *
+     */
+    QString fileName() const {return m_fileName;}
+
+
+    /**
+     * Sets the filename of the GLM scene.
+     *
+     * @param filename The new filename of the GLM scene.
+     *
+     */
+    void setFileName(const QString& fileName=QString());
+
+
+    /**
+     * Gets the backFaceCulling flag of the GLM scene.
+     *
+     * @return The backFaceCulling flag of the GLM scene.
+     *
+     */
+    bool backFaceCulling() const {return m_backFaceCulling;}
+
+
+    /**
+     * Sets the backFaceCulling flag of the GLM scene.
+     *
+     * @param bEnable The new backFaceCulling flag of the GLM scene.
+     *
+     */
+    void setBackFaceCulling(bool bEnable) {m_backFaceCulling=bEnable;}
+
+
+    /**
+     * Gets the smoothing flag of the GLM scene.
+     *
+     * @return The smoothing flag of the GLM scene.
+     *
+     */
+    bool smoothing() const {return m_smoothing;}
+
+
+    /**
+     * Sets the smoothing flag of the GLM scene.
+     *
+     * @param bEnable The new smoothing flag of the GLM scene.
+     *
+     */
+    void setSmoothing(bool bEnable) {m_smoothing=bEnable;}
+
+
+    /**
+     * Loads the GLM scene from a QDomElement.
+     *
+     * Only the contents are loaded. After this, the model is loaded from the
+     * filename. The model is not in the QDomElement.
+     *
+     * @param element The QDomElement to read from.
+     *
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+
+    /**
+     * Writes the contents in a QDomDocument.
+     *
+     * Only the contents are stored in the QDomElement. The model is not stored
+     * in it.
+     *
+     * @param name The name of the element.
+     * @param doc The document whom belongs the element.
+     *
+     * @return The QDomElement to add.
+     *
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+
+    /**
+     * Gets the name of GLM scene type, stored in g_scene_name.
+     *
+     * @return The name of GLM scene type, stored in g_scene_name.
+     *
+     */
+    const QString& scene_name(void) const {return g_scene_name;}
+
+
+    /// Public static const scene name for the GLM scene.
+    static const QString g_scene_name;
+
+
+private:
+
+
+    ///File name of the model.
+    QString m_fileName;
+
+
+    /// True to cull back face of the model.
+    bool m_backFaceCulling;
+
+
+    /// True to smooth surface of the model.
+    bool m_smoothing;
+
+
+    /// glm model data structure.
+    GLMmodel* m_pModel;
+
+
+    /// gml model display list index.
+    GLuint m_modelIndex;
+
+
+};
+
+
+#endif // __DEFAULT_MODEL_SCENE_CONTENT_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.cpp	(revision 4)
@@ -0,0 +1,109 @@
+#include "DefaultModelSceneWidget.h"
+
+
+/**
+ * Default constructor.
+ *
+ */
+DefaultModelSceneWidget::DefaultModelSceneWidget(SceneInterface *plugin, QWidget* pParent, Qt::WFlags flag): SceneWidget(plugin, pParent, flag), m_content(plugin)
+{
+    setupUi (this);
+    updateGUI();
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultModelSceneWidget::~DefaultModelSceneWidget()
+{
+}
+
+
+/**
+ * Updates the widget.
+ *
+ * This method can be used it two ways: to force a refresh or to update the
+ * data of the widget.
+ *
+ * @param content A const pointer on the contents to be used for the widget.
+ *                This contents will be duplicated in the widget. If content
+ *                is NULL, the current content are used and the refresh is
+ *                forced. If no content are given, NULL is used.
+ *
+ */
+void DefaultModelSceneWidget::updateGUI(const SceneContent* _content)
+{
+    if (_content)
+    {
+	const DefaultModelSceneContent *content = static_cast<const DefaultModelSceneContent*>(_content);
+	Q_ASSERT(NULL!=content); // <-- Assume that the conversion was successful
+	m_content.copy_from(*content);
+    }
+    // From now, we will only use m_content
+    modelFileNameEdit->setText(m_content.fileName());
+    modelCullingCheckBox->setChecked(m_content.backFaceCulling());
+    modelSmoothingCheckBox->setChecked(m_content.smoothing());
+}
+
+
+/**
+ * [private slot] Called when the "filename" field is edited.
+ *
+ */
+void DefaultModelSceneWidget::on_modelFileNameEdit_editingFinished()
+{
+    QString fileName = modelFileNameEdit->text();
+    if (fileName!=m_content.fileName())
+    {
+	m_content.setFileName(fileName);
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the "browse" button is pressed.
+ *
+ */
+void DefaultModelSceneWidget::on_modelBrowseButton_clicked()
+{
+    QString fileName = QFileDialog::getOpenFileName(this, "Choose a file to open", modelFileNameEdit->text(), "Model files (*.obj)");
+    if (!fileName.isEmpty()) {
+        modelFileNameEdit->setText(fileName);
+        on_modelFileNameEdit_editingFinished();
+    }
+}
+
+
+/**
+ * [private slot] Called when the culling checkbox state changes.
+ *
+ * @param checked true if the checkbox is checked.
+ *
+ */
+void DefaultModelSceneWidget::on_modelCullingCheckBox_toggled(bool checked)
+{
+    if (checked!=m_content.backFaceCulling())
+    {
+	m_content.setBackFaceCulling(checked);
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the smooth checkbox state changes.
+ *
+ * @param checked true if the checkbox is checked.
+ *
+ */
+void DefaultModelSceneWidget::on_modelSmoothingCheckBox_toggled(bool checked)
+{
+    if (checked!=m_content.smoothing())
+    {
+	m_content.setSmoothing(checked);
+	emit dataChanged(m_content);
+    }
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultModelSceneWidget.h	(revision 4)
@@ -0,0 +1,126 @@
+#ifndef __DEFAULT_MODEL_SCENE_WIDGET_H__
+#define __DEFAULT_MODEL_SCENE_WIDGET_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes the ui_ header
+#include "ui_defaultmodelscenewidget.h"
+
+// Includes local headers
+#include "DefaultModelSceneContent.h"
+
+
+/**
+ * Implementation of the DefaultModelSceneWidget class.
+ *
+ * This widget is used in a stacked widget with all the other scene,
+ * to configure the GLM scene.
+ *
+ */
+class DefaultModelSceneWidget : public SceneWidget,
+				private Ui::DefaultModelSceneWidget
+{
+    Q_OBJECT
+		
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    DefaultModelSceneWidget(SceneInterface *plugin, QWidget* pParent=0, Qt::WFlags flag=0);
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultModelSceneWidget();
+
+
+    /**
+     * Updates the widget.
+     *
+     * This method can be used it two ways: to force a refresh or to update the
+     * data of the widget.
+     *
+     * @param content A const pointer on the contents to be used for the widget.
+     *                This contents will be duplicated in the widget. If content
+     *                is NULL, the current content are used and the refresh is
+     *                forced. If no content are given, NULL is used.
+     *
+     */
+    void updateGUI(const SceneContent* data=NULL);
+
+
+    /**
+     * Gets the widget contents.
+     *
+     * @return A const reference on the content of the widget.
+     *
+     */
+    const SceneContent& content(void) const {return m_content;}
+
+
+signals:
+
+
+    /**
+     * [signal] Notify that the contents of the widget have changed.
+     *
+     * This signal is emitted each time that a field is changed.
+     *
+     * @param content A const reference on the new contents (the same as 
+     *                returned by the content() method).
+     *
+     */
+    virtual void dataChanged(const SceneContent&);
+
+
+private slots:
+
+
+    /**
+     * [private slot] Called when the "filename" field is edited.
+     *
+     */
+    void on_modelFileNameEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the "browse" button is pressed.
+     *
+     */
+    void on_modelBrowseButton_clicked();
+
+
+    /**
+     * [private slot] Called when the culling checkbox state changes.
+     *
+     * @param checked true if the checkbox is checked.
+     */
+    void on_modelCullingCheckBox_toggled(bool checked);
+
+
+    /**
+     * [private slot] Called when the smooth checkbox state changes.
+     *
+     * @param checked true if the checkbox is checked.
+     *
+     */
+    void on_modelSmoothingCheckBox_toggled(bool checked);
+
+
+private:
+
+
+    /// The current DefaultModelSceneContent of the widget.
+    DefaultModelSceneContent m_content;
+
+};
+
+
+#endif // __DEFAULT_MODEL_SCENE_WIDGET_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.cpp	(revision 4)
@@ -0,0 +1,315 @@
+#include "DefaultProjectorData.h"
+#include <stdlib.h>
+#include <GL/glut.h>
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif // M_PI
+#define RAD(angle) ((angle)*M_PI/180.f)
+
+
+const QString DefaultPluginData::g_projector_name=QObject::tr("Standard Frustum");
+
+
+/**
+ * Default constructor fot the DefaultPluginData.
+ *
+ */
+DefaultPluginData::DefaultPluginData(ProjectorInterface* plugin, float fov, float aspectRatio, float nearDist, float farDist, float offaxisX, float offaxisY):
+    ProjectorData(plugin),
+    m_fov(fov),
+    m_aspectRatio(aspectRatio),
+    m_nearDist(nearDist),
+    m_farDist(farDist),
+    m_offaxisX(offaxisX),
+    m_offaxisY(offaxisY),
+    m_visibleFar(1.2f)
+{
+}
+
+
+/**
+ * Destructor fot the DefaultPluginData.
+ *
+ */
+DefaultPluginData::~DefaultPluginData()
+{
+}
+
+
+/**
+ * Implements the copy from other datas.
+ *
+ * This method is used by the copy constructor.
+ *
+ * @param data The source data.
+ *
+ * @return true if the copy is ok, false otherwise. The copy can fail if
+ *         ProjectorData is not a DefaultPluginData.
+ *
+ * @seealso is_equal_to
+ *
+ */
+bool DefaultPluginData::copy_from(const ProjectorData& data) 
+{
+    if (!ProjectorData::copy_from(data)) return false;
+    Q_ASSERT(NULL!=plugin());
+    Q_ASSERT(NULL!=data.plugin());
+    const DefaultPluginData& _data = static_cast<const DefaultPluginData&>(data);
+    m_fov = _data.m_fov;
+    m_aspectRatio = _data.m_aspectRatio;
+    m_nearDist = _data.m_nearDist;
+    m_farDist = _data.m_farDist;
+    m_offaxisX = _data.m_offaxisX;
+    m_offaxisY = _data.m_offaxisY;
+    m_visibleFar = _data.m_visibleFar;
+    return true;
+}
+
+
+/**
+ * Implements the egality-test with other datas.
+ *
+ * This could be an operator==.
+ *
+ * @param data The data to test with.
+ *
+ * @return true if the data are equal, false otherwise. The test can fail if
+ *         the data have different parameters, but also it ProjectorData is
+ *         not a DefaultPluginData.
+ *
+ * @seealso copy_from
+ *
+ */
+bool DefaultPluginData::is_equal_to(const ProjectorData& data) const
+{
+    if (!ProjectorData::is_equal_to(data)) return false;
+    const DefaultPluginData& _data = static_cast<const DefaultPluginData&>(data);
+    return m_fov==_data.m_fov&&
+	m_aspectRatio==_data.m_aspectRatio&&
+	m_nearDist==_data.m_nearDist&&
+	m_farDist==_data.m_farDist&&
+	m_offaxisX==_data.m_offaxisX&&
+	m_offaxisY==_data.m_offaxisY&&
+	m_visibleFar==_data.m_visibleFar;
+}
+
+
+/**
+ * Draws the frustum (a truncated pyramid).
+ *
+ * This method draws the frustum from outside. If the frustum is selected,
+ * the lines are a little bigger.
+ *
+ * @param bSelected true if the frustum is selected.
+ *
+ * @seealso copy_from
+ *
+ */
+void DefaultPluginData::draw(bool bSelected)
+{
+    QColor m_color(0,0,255);
+
+    if (m_bShow)
+    {
+        glPushMatrix();
+        glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LINE_BIT);
+
+        if (bSelected)
+            glLineWidth(3.0f);
+
+        float left =  -tan(RAD(m_fov/2.0f)) * m_aspectRatio + m_offaxisX;
+        float right =  tan(RAD(m_fov/2.0f)) * m_aspectRatio + m_offaxisX;
+        float top =   -tan(RAD(m_fov/2.0f)) + m_offaxisY;
+        float bottom = tan(RAD(m_fov/2.0f)) + m_offaxisY;
+        float nearDist = m_nearDist;
+        float farDist = m_farDist;
+        if (m_visibleFar < farDist)
+            farDist = m_visibleFar;
+
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        glDisable(GL_LIGHTING);
+
+	glBegin(GL_LINE_LOOP);
+        glVertex3f(nearDist*left,  nearDist*bottom, -nearDist);
+        glVertex3f(nearDist*right, nearDist*bottom, -nearDist);
+        glVertex3f(nearDist*right, nearDist*top,    -nearDist);
+        glVertex3f(nearDist*left,  nearDist*top,    -nearDist);
+        glEnd();
+        glBegin(GL_LINE_LOOP);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glVertex3f(farDist*left,  farDist*top,    -farDist);
+        glEnd();
+        glBegin(GL_LINES);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*top,    -farDist);
+        glEnd();
+
+        glColor4f((float)m_color.red()/255.0f, (float)m_color.green()/255.0f, (float)m_color.blue()/255.0f, 0.25f);
+        glEnable(GL_LIGHTING);
+        glEnable(GL_BLEND);
+        glDepthMask(false);
+
+        glBegin(GL_TRIANGLES);
+        glNormal3f(0.0f, cos(RAD(m_fov)/2.0f), -sin(RAD(m_fov)/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left,  farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glNormal3f( cos(RAD(m_fov)*m_aspectRatio/2.0f),
+                    0.0f,
+		    -sin(RAD(m_fov)*m_aspectRatio/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*bottom, -farDist);
+        glVertex3f(farDist*right, farDist*top,    -farDist);
+        glNormal3f(0.0f, -cos(RAD(m_fov)/2.0f), -sin(RAD(m_fov)/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*right, farDist*top, -farDist);
+        glVertex3f(farDist*left,  farDist*top, -farDist);
+        glNormal3f(-cos(RAD(m_fov)*m_aspectRatio/2.0f),
+		   0.0f,
+                   -sin(RAD(m_fov)*m_aspectRatio/2.0f));
+        glVertex3f(0.0f, 0.0f, 0.0f);
+        glVertex3f(farDist*left, farDist*top,    -farDist);
+        glVertex3f(farDist*left, farDist*bottom, -farDist);
+        glEnd();
+
+        glDepthMask(true);
+        glPopAttrib();
+        glPopMatrix();
+    }
+}
+
+
+/**
+ * Begins the draw through the frustum.
+ *
+ * The draw must end with a endDraw().
+ *
+ * This is the same than glFrustum(), with some glPush...() before.
+ *
+ * @seealso endDraw
+ *
+ */
+void DefaultPluginData::beginDraw(void)
+{
+    // Get the previous matrix mode
+    GLint previous_matrix_mode=-1;
+    glGetIntegerv(GL_MATRIX_MODE, &previous_matrix_mode);
+
+    // Push and load the new projection matrix
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+    glFrustum((-tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, 
+	      ( tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, 
+	      (-tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, 
+	      ( tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, 
+	      m_nearDist, 
+	      m_farDist);
+
+    // Restore the previous matrix mode
+    glMatrixMode(previous_matrix_mode);
+}
+
+
+/**
+ * Ends the draw through the frustum.
+ *
+ * Must be used each time a draw through the projector has begun with a
+ * beginDraw().
+ *
+ * This is the same than some glPop...().
+ *
+ * @seealso beginDraw
+ *
+ */
+void DefaultPluginData::endDraw(void)
+{
+    // Get the previous matrix mode
+    GLint previous_matrix=-1;
+    glGetIntegerv(GL_MATRIX_MODE, &previous_matrix);
+    // Pop the projection matrix stack
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    // Restore the previous matrix mode
+    glMatrixMode(previous_matrix);
+}
+
+
+/**
+ * Begins the projection.
+ *
+ * The projection must end with a endProjection().
+ *
+ * This is the same than glFrustum(), without anything else.
+ * beginDraw and beginProjection are quite close and it is perhaps to merge
+ * them, but for the moment, to respect the Projection Designer
+ * implementation, it will be let like this.
+ *
+ * endProjection is not implemented here because it does nothing more than
+ * the ProjectorData::endProjection().
+ *
+ */
+void DefaultPluginData::beginProjection(void)
+{
+    glFrustum((-tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, 
+	      ( tan(RAD(m_fov) / 2.0 * m_aspectRatio) - m_offaxisX) * m_nearDist, 
+	      (-tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, 
+	      ( tan(RAD(m_fov) / 2.0) + m_offaxisY) * m_nearDist, 
+	      m_nearDist, 
+	      m_farDist);
+}
+
+
+/**
+ * Loads the frustum from a QDomElement.
+ *
+ * @param element The QDomElement to read from.
+ *
+ */
+void DefaultPluginData::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+	m_fov=element.attribute("fov").toFloat();
+	m_aspectRatio=element.attribute("aspectRatio").toFloat();
+	m_nearDist=element.attribute("near").toFloat();
+	m_farDist=element.attribute("far").toFloat();
+	m_offaxisX=element.attribute("offaxisX").toFloat();
+	m_offaxisY=element.attribute("offaxisY").toFloat();
+	m_visibleFar=element.attribute("visibleFar").toFloat();
+	ProjectorData::initFromDOMElement(element);
+    }
+}
+
+
+/**
+ * Writes the frustum in a QDomDocument.
+ *
+ * @param name The name of the element.
+ * @param doc The document whom belongs the element.
+ *
+ * @return The QDomElement to add.
+ *
+ */
+QDomElement DefaultPluginData::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = ProjectorData::domElement(name, doc);
+    de.setAttribute("fov", m_fov);
+    de.setAttribute("aspectRatio", m_aspectRatio);
+    de.setAttribute("near", m_nearDist);
+    de.setAttribute("far", m_farDist);
+    de.setAttribute("offaxisX", m_offaxisX);
+    de.setAttribute("offaxisY", m_offaxisY);
+    de.setAttribute("visibleFar", m_visibleFar);
+    return de;
+}
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorData.h	(revision 4)
@@ -0,0 +1,324 @@
+#ifndef __DEFAULT_PROJECTOR_DATA_H__
+#define __DEFAULT_PROJECTOR_DATA_H__
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+
+/**
+ * Implementation of the DefaultProjectorWidget class.
+ *
+ * This class is where the projector is really implemented. Attributes are the
+ * frustum parameters. Methods allow you to draw the frustum either *from* the
+ * frustum as from a different point of view, in order to *see* the frustum.
+ *
+ */
+class DefaultPluginData: public ProjectorData
+{
+
+public:
+
+
+    /**
+     * Default constructor fot the DefaultPluginData.
+     *
+     */
+    DefaultPluginData (ProjectorInterface* plugin, float fov=30.f, float aspectRatio=4.f/3.f, float near=0.1f, float far=100.f, float offaxisX=0.f, float offaxisY=0.f);
+
+
+    /**
+     * Copy constructor fot the DefaultPluginData.
+     *
+     */
+    DefaultPluginData (const DefaultPluginData& data): ProjectorData(data) {copy_from(data);}
+
+
+    /**
+     * Destructor fot the DefaultPluginData.
+     *
+     */
+    ~DefaultPluginData ();
+
+
+    /**
+     * Implements the copy from other datas.
+     *
+     * This method is used by the copy constructor.
+     *
+     * @param data The source data.
+     *
+     * @return true if the copy is ok, false otherwise. The copy can fail if
+     *         ProjectorData is not a DefaultPluginData.
+     *
+     * @seealso is_equal_to
+     *
+     */
+    bool copy_from(const ProjectorData& data);
+
+
+    /**
+     * Implements the egality-test with other datas.
+     *
+     * This could be an operator==.
+     *
+     * @param data The data to test with.
+     *
+     * @return true if the data are equal, false otherwise. The test can fail if
+     *         the data have different parameters, but also it ProjectorData is
+     *         not a DefaultPluginData.
+     *
+     * @seealso copy_from
+     *
+     */
+    bool is_equal_to(const ProjectorData& data) const;
+
+
+    /**
+     * Draws the frustum (a truncated pyramid).
+     *
+     * This method draws the frustum from outside. If the frustum is selected,
+     * the lines are a little bigger.
+     *
+     * @param bSelected true if the frustum is selected.
+     *
+     */
+    void draw(bool bSelected);
+
+
+    /**
+     * Begins the draw through the frustum.
+     *
+     * The draw must end with a endDraw().
+     *
+     * This is the same than glFrustum(), with some glPush...() before.
+     *
+     * @seealso endDraw
+     *
+     */
+    void beginDraw(void);
+
+
+    /**
+     * Ends the draw through the frustum.
+     *
+     * Must be used each time a draw through the projector has begun with a
+     * beginDraw().
+     *
+     * This is the same than some glPop...().
+     *
+     * @seealso beginDraw
+     *
+     */
+    void endDraw(void);
+
+
+    /**
+     * Begins the projection.
+     *
+     * The projection must end with a endProjection().
+     *
+     * This is the same than glFrustum(), without anything else.
+     * beginDraw and beginProjection are quite close and it is perhaps to merge
+     * them, but for the moment, to respect the Projection Designer
+     * implementation, it will be let like this.
+     *
+     * endProjection is not implemented here because it does nothing more than
+     * the ProjectorData::endProjection().
+     *
+     */
+    void beginProjection(void);
+
+
+    /**
+     * Sets the field of view.
+     *
+     * @param fov The new field of view.
+     *
+     */
+    void setFov(float fov) {m_fov=fov;}
+
+
+    /**
+     * Gets the field of view.
+     *
+     * @return The field of view of the projector.
+     *
+     */
+    float fov() const {return m_fov;}
+
+
+    /**
+     * Sets the aspect ratio.
+     *
+     * @param aspectRatio The new aspect ratio.
+     *
+     */
+    void setAspectRatio(float aspectRatio) {m_aspectRatio=aspectRatio;}
+
+
+    /**
+     * Gets the aspect ratio.
+     *
+     * @return The aspect ratio of the projector.
+     *
+     */
+    float aspectRatio() const {return m_aspectRatio;}
+
+
+    /**
+     * Sets the near distance of the frustum.
+     *
+     * @param nearDist The new near distance of the frustum.
+     *
+     */
+    void setNearDist(float nearDist) {m_nearDist=nearDist;}
+
+
+    /**
+     * Gets the near distance of the frustum.
+     *
+     * @return The near distance of the frustum.
+     *
+     */
+    float nearDist() const {return m_nearDist;}
+
+
+    /**
+     * Sets the far distance of the frustum.
+     *
+     * @param farDist The new far distance of the frustum.
+     *
+     */
+    void setFarDist(float farDist) {m_farDist=farDist;}
+
+
+    /**
+     * Gets the far distance of the frustum.
+     *
+     * @return The far distance of the frustum.
+     *
+     */
+    float farDist() const {return m_farDist;}
+
+
+    /**
+     * Sets the off-axis X of the frustum.
+     *
+     * @param offaxisX The new off-axis X of the frustum.
+     *
+     */
+    void setOffaxisX(float offaxisX) {m_offaxisX=offaxisX;}
+
+
+    /**
+     * Gets the off-axis X of the frustum.
+     *
+     * @return The off-axis X of the frustum.
+     *
+     */
+    float offaxisX() const {return m_offaxisX;}
+
+
+    /**
+     * Sets the off-axis Y of the frustum.
+     *
+     * @param offaxisY The new off-axis Y of the frustum.
+     *
+     */
+    void setOffaxisY(float offaxisY) {m_offaxisY=offaxisY;}
+
+
+    /**
+     * Gets the off-axis Y of the frustum.
+     *
+     * @return The off-axis Y of the frustum.
+     *
+     */
+    float offaxisY() const {return m_offaxisY;}
+
+
+    /**
+     * Sets the visible distance of the frustum.
+     *
+     * @param visibleFar The new visible distance of the frustum.
+     *
+     */
+    void setVisibleFar(float visibleFar) {m_visibleFar=visibleFar;}
+
+
+    /**
+     * Gets the visible distance of the frustum.
+     *
+     * @return The visible distance of the frustum.
+     *
+     */
+    float visibleFar() const {return m_visibleFar;}
+
+
+    /**
+     * Loads the frustum from a QDomElement.
+     *
+     * @param element The QDomElement to read from.
+     *
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+
+    /**
+     * Writes the frustum in a QDomDocument.
+     *
+     * @param name The name of the element.
+     * @param doc The document whom belongs the element.
+     *
+     * @return The QDomElement to add.
+     *
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+
+    /**
+     * Gets the name of projector type, stored in g_projector_name.
+     *
+     * @return The name of projector type, stored in g_projector_name.
+     *
+     */
+    const QString& projector(void) const {return g_projector_name;}
+
+
+    /// Public static const projector name.
+    static const QString g_projector_name;
+
+
+private:
+
+
+    /// Field of view of the frustum.
+    float m_fov;
+
+
+    /// Aspect ratio of the frustum.
+    float m_aspectRatio;
+
+
+    /// Near distance of the frustum.
+    float m_nearDist;
+
+
+    /// Far distance of the frustum.
+    float m_farDist;
+
+
+    /// Off-axis X of the frustum.
+    float m_offaxisX;
+
+
+    /// Off-axis Y of the frustum.
+    float m_offaxisY;
+
+
+    /// Visible far of the frustum.
+    float m_visibleFar;
+
+};
+
+#endif // __DEFAULT_PROJECTOR_DATA_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.cpp	(revision 4)
@@ -0,0 +1,153 @@
+#include "DefaultProjectorWidget.h"
+
+
+/**
+ * Format the value in a QString.
+ *
+ * This procedure is implemented for convenience, because it was used in the original Projection Designer.
+ *
+ * @param value The value to format.
+ *
+ * @return The formatted QString.
+ *
+ */
+static QString formatValue(double value)
+{
+    return QString::number(value, 'f', 4);
+}
+
+
+/**
+ * Default constructor fot the DefaultProjectorWidget.
+ *
+ */
+DefaultProjectorWidget::DefaultProjectorWidget(ProjectorInterface *plugin, QWidget* pParent, Qt::WFlags flag): ProjectorWidget(plugin, pParent, flag), m_data(plugin)
+{
+    setupUi (this);
+    updateGUI();
+}
+
+
+/**
+ * Destructor fot the DefaultProjectorWidget.
+ *
+ */
+DefaultProjectorWidget::~DefaultProjectorWidget()
+{
+}
+
+
+/**
+ * Updates the widget.
+ *
+ * This method can be used it two ways: to force a refresh or to update the
+ * data of the widget.
+ *
+ * @param data A const pointer on the data to be used for the widget. This
+ *             data will be duplicated in the widget. If data is NULL, the
+ *             current data are used and the refresh is forced.
+ *
+ */
+void DefaultProjectorWidget::updateGUI(const ProjectorData* data)
+{
+    if (NULL!=data) m_data.copy_from(*data);
+    fovEdit->setText(formatValue(m_data.fov()));
+    aspectRatioEdit->setText(QString::number(m_data.aspectRatio(), 'g'));
+    nearEdit->setText(QString::number(m_data.nearDist(), 'g'));
+    farEdit->setText(QString::number(m_data.farDist(), 'g'));
+    offaxisXEdit->setText(formatValue(m_data.offaxisX()));
+    offaxisYEdit->setText(formatValue(m_data.offaxisY()));
+}
+
+
+/**
+ * Clears the fields of the widget.
+ *
+ * This method is typically used when the widget will be disabled (if no
+ * channel is specified in Projection Designer, the widget is visible but
+ * disabled: fields must be empty).
+ *
+ */
+void DefaultProjectorWidget::clear(void)
+{
+    fovEdit->setText("");
+    aspectRatioEdit->setText("");
+    nearEdit->setText("");
+    farEdit->setText("");
+    offaxisXEdit->setText("");
+    offaxisYEdit->setText("");
+}
+
+
+/**
+ * [private slot] Called when the Fov changes.
+ *
+ */
+void DefaultProjectorWidget::on_fovEdit_editingFinished()
+{
+    m_data.setFov(fovEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
+/**
+ * [private slot] Called when the Aspect Ratio changes.
+ *
+ */
+void DefaultProjectorWidget::on_aspectRatioEdit_editingFinished()
+{
+    m_data.setAspectRatio(aspectRatioEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
+/**
+ * [private slot] Called when the Near changes.
+ *
+ */
+void DefaultProjectorWidget::on_nearEdit_editingFinished()
+{
+    m_data.setNearDist(nearEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
+/**
+ * [private slot] Called when the Far changes.
+ *
+ */
+void DefaultProjectorWidget::on_farEdit_editingFinished()
+{
+    m_data.setFarDist(farEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
+/**
+ * [private slot] Called when the OffAxis-X changes.
+ *
+ */
+void DefaultProjectorWidget::on_offaxisXEdit_editingFinished()
+{
+    m_data.setOffaxisX(offaxisXEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
+/**
+ * [private slot] Called when the OffAxis-Y changes.
+ *
+ */
+void DefaultProjectorWidget::on_offaxisYEdit_editingFinished()
+{
+    m_data.setOffaxisY(offaxisYEdit->text().toFloat());
+    updateGUI();
+    emit dataChanged(m_data);
+}
+
+
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultProjectorWidget.h	(revision 4)
@@ -0,0 +1,147 @@
+#ifndef __DEFAULT_PROJECTOR_WIDGET_H__
+#define __DEFAULT_PROJECTOR_WIDGET_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes the ui_ header
+#include "ui_defaultprojectorwidget.h"
+
+// Includes local headers
+#include "DefaultProjectorData.h"
+
+
+/**
+ * Implementation of the DefaultProjectorWidget class.
+ *
+ * This widget is used in a stacked widget with all the other projectors, to
+ * configure the projector.
+ *
+ */
+class DefaultProjectorWidget : public ProjectorWidget,
+			       private Ui::DefaultProjectorWidget
+{
+    Q_OBJECT
+		
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    DefaultProjectorWidget(ProjectorInterface *plugin, QWidget* pParent=0, Qt::WFlags flag=0);
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultProjectorWidget();
+
+
+    /**
+     * Updates the widget.
+     *
+     * This method can be used it two ways: to force a refresh or to update the
+     * data of the widget.
+     *
+     * @param data A const pointer on the data to be used for the widget. This
+     *             data will be duplicated in the widget. If data is NULL, the
+     *             current data are used and the refresh is forced. If no data
+     *             is given, NULL is used.
+     *
+     */
+    void updateGUI(const ProjectorData* data=NULL);
+
+
+    /**
+     * Clears the fields of the widget.
+     *
+     * This method is typically used when the widget will be disabled (if no
+     * channel is specified in Projection Designer, the widget is visible but
+     * disabled: fields must be empty).
+     *
+     */
+    void clear(void);
+
+
+    /**
+     * Gets the widget data.
+     *
+     * @return A const reference on the data of the widget.
+     *
+     */
+    const ProjectorData& data(void) const {return m_data;}
+
+
+signals:
+
+
+    /**
+     * [signal] Notify that the data of the widget have changed.
+     *
+     * This signal is emitted each time that a field is changed.
+     *
+     * @param data A const reference on the new data (the same as returned by
+     *             the data() method).
+     *
+     */
+    virtual void dataChanged(const ProjectorData& data);
+
+
+private slots:
+
+
+    /**
+     * [private slot] Called when the Fov changes.
+     *
+     */
+    void on_fovEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the Aspect Ratio changes.
+     *
+     */
+    void on_aspectRatioEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the Near changes.
+     *
+     */
+    void on_nearEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the Far changes.
+     *
+     */
+    void on_farEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the OffAxis-X changes.
+     *
+     */
+    void on_offaxisXEdit_editingFinished();
+
+
+    /**
+     * [private slot] Called when the OffAxis-Y changes.
+     *
+     */
+    void on_offaxisYEdit_editingFinished();
+
+
+private:
+
+
+    /// The current DefaultPluginData of the widget.
+    DefaultPluginData m_data;
+
+};
+
+#endif // __DEFAULT_PROJECTOR_WIDGET_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.cpp	(revision 4)
@@ -0,0 +1,145 @@
+#include "DefaultTeapotSceneContent.h"
+
+
+const QString DefaultTeapotSceneContent::g_scene_name=QObject::tr("Teapot");
+
+
+/**
+ * Default constructor
+ *
+ */
+DefaultTeapotSceneContent::DefaultTeapotSceneContent(SceneInterface* plugin):
+    SceneContent(plugin),
+    m_bWireframe(true),
+    m_iWidth(1)
+{
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultTeapotSceneContent::~DefaultTeapotSceneContent()
+{
+}
+
+
+/**
+ * Implements the copy from other contents.
+ *
+ * This method is used by the copy constructor.
+ *
+ * @param content The source content to copy from.
+ *
+ * @return true if the copy is ok, false otherwise. The copy can fail if
+ *         SceneContent is not a DefaultTeapotSceneContent.
+ *
+ * @seealso is_equal_to
+ *
+ */
+bool DefaultTeapotSceneContent::copy_from(const SceneContent& data) 
+{
+    if (!SceneContent::copy_from(data)) return false;
+    Q_ASSERT(NULL!=plugin());
+    Q_ASSERT(NULL!=data.plugin());
+    const DefaultTeapotSceneContent& _data = static_cast<const DefaultTeapotSceneContent&>(data);
+    m_bWireframe = _data.m_bWireframe;
+    m_iWidth     = _data.m_iWidth;
+    return true;
+}
+
+
+/**
+ * Implements the egality-test with other contents.
+ *
+ * This could be an operator==.
+ *
+ * @param content The content to compare with.
+ *
+ * @return true if the content are equal, false otherwise. The test can
+ *         fail if the contents have different parameters, but also it
+ *         SceneContent is not a DefaultTeapotSceneContent.
+ *
+ * @seealso copy_from
+ *
+ */
+bool DefaultTeapotSceneContent::is_equal_to(const SceneContent& data) const
+{
+    if (!SceneContent::is_equal_to(data)) return false;
+    const DefaultTeapotSceneContent& _data = static_cast<const DefaultTeapotSceneContent&>(data);
+    if (m_bWireframe)
+    {
+	return m_bWireframe==_data.m_bWireframe
+	    && m_iWidth==_data.m_iWidth;
+    }
+    else
+    {
+	return m_bWireframe==_data.m_bWireframe;
+    }
+}
+
+
+/**
+ * Draws the teapot.
+ *
+ * @param glWidget The QGLWidget that own the OpenGL context.
+ * @param cameraMatrix The camera matrix that must be use.
+ *
+ */
+void DefaultTeapotSceneContent::draw(QGLWidget *glWidget, const float* cameraMatrix)
+{
+    Q_UNUSED (glWidget);
+    Q_UNUSED(cameraMatrix);
+    glPushAttrib(GL_ENABLE_BIT);
+    glDisable(GL_TEXTURE_2D);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    glPushMatrix();
+    if (!m_bWireframe)
+    {
+	glutSolidTeapot(0.25);
+    }
+    else
+    {
+	glLineWidth(m_iWidth);
+	glutWireTeapot(0.25);
+    }
+    glPopMatrix();
+    glPopAttrib();
+}
+
+
+/**
+ * Loads the teapot from a QDomElement.
+ *
+ * @param element The QDomElement to read from.
+ *
+ */
+void DefaultTeapotSceneContent::initFromDOMElement(const QDomElement& element)
+{
+    if (!element.isNull())
+    {
+	m_bWireframe=element.attribute("wireframe").toLower()=="true";
+	m_iWidth=element.attribute("width").toInt(); // <-- 0 if not present
+	SceneContent::initFromDOMElement(element);
+    }
+}
+
+
+/**
+ * Writes the teapot in a QDomDocument.
+ *
+ * @param name The name of the element.
+ * @param doc The document whom belongs the element.
+ *
+ * @return The QDomElement to add.
+ *
+ */
+QDomElement DefaultTeapotSceneContent::domElement(const QString& name, QDomDocument& doc) const
+{
+    QDomElement de = SceneContent::domElement(name, doc);
+    de.setAttribute("wireframe", (m_bWireframe)?"true":"false");
+    de.setAttribute("width",     m_iWidth);
+    return de;
+}
+
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneContent.h	(revision 4)
@@ -0,0 +1,188 @@
+#ifndef __DEFAULT_TEAPOT_SCENE_CONTENT_H__
+#define __DEFAULT_TEAPOT_SCENE_CONTENT_H__
+
+// Includes system headers
+#include <stdlib.h>
+#include <GL/glut.h>
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+
+/**
+ * This class implements the contents of the teapot scene of the default plugin.
+ *
+ * The teapot is a basic scene content. It only has 2 parameters, which are the
+ * flag that determine if the teapot will be drawn using solid or wireframe
+ * representation, and the width of the lines for the wireframe representation.
+ *
+ */
+class DefaultTeapotSceneContent: public SceneContent
+{
+
+public:
+
+
+    /**
+     * Default constructor
+     *
+     */
+    DefaultTeapotSceneContent (SceneInterface* plugin);
+
+
+    /**
+     * Copy constructor.
+     *
+     * Uses copy_from() to make the copy.
+     *
+     */
+    DefaultTeapotSceneContent (const DefaultTeapotSceneContent& data): SceneContent(data) {copy_from(data);}
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultTeapotSceneContent ();
+
+
+    /**
+     * Implements the copy from other contents.
+     *
+     * This method is used by the copy constructor.
+     *
+     * @param content The source content to copy from.
+     *
+     * @return true if the copy is ok, false otherwise. The copy can fail if
+     *         SceneContent is not a DefaultTeapotSceneContent.
+     *
+     * @seealso is_equal_to
+     *
+     */
+    bool copy_from(const SceneContent& content);
+
+
+    /**
+     * Implements the egality-test with other contents.
+     *
+     * This could be an operator==.
+     *
+     * @param content The content to compare with.
+     *
+     * @return true if the content are equal, false otherwise. The test can
+     *         fail if the contents have different parameters, but also it
+     *         SceneContent is not a DefaultTeapotSceneContent.
+     *
+     * @seealso copy_from
+     *
+     */
+    bool is_equal_to(const SceneContent& content) const;
+
+
+    /**
+     * Draws the teapot.
+     *
+     * @param glWidget The QGLWidget that own the OpenGL context.
+     * @param cameraMatrix The camera matrix that must be use.
+     *
+     */
+    void draw(QGLWidget* glWidget, const float* cameraMatrix);
+
+
+    /**
+     * Resets the teapot.
+     *
+     * This is a pure virtual method of SceneContent.
+     * This one does nothing.
+     *
+     */
+    void reset (void) {}
+
+
+    /**
+     * Gets the wireframe flag of the teapot.
+     *
+     * @return The wireframe flag of the teapot.
+     *
+     */
+    bool wireframe(void) const {return m_bWireframe;}
+
+
+    /**
+     * Sets the wireframe flag of the teapot.
+     *
+     * @param wireframe The new wireframe flag of the teapot.
+     *
+     */
+    void setWireframe(bool wireframe) {m_bWireframe=wireframe;}
+
+
+    /**
+     * Gets the width of the lines of the teapot.
+     *
+     * @return The width of the lines of the teapot.
+     *
+     */
+    int width(void) const {return m_iWidth;}
+
+
+    /**
+     * Sets the width of the lines of the teapot.
+     *
+     * @param width The new width of the lines of the teapot.
+     *
+     */
+    void setWidth(int width) {m_iWidth=width;}
+
+
+    /**
+     * Loads the teapot from a QDomElement.
+     *
+     * @param element The QDomElement to read from.
+     *
+     */
+    void initFromDOMElement(const QDomElement& element);
+
+
+    /**
+     * Writes the teapot in a QDomDocument.
+     *
+     * @param name The name of the element.
+     * @param doc The document whom belongs the element.
+     *
+     * @return The QDomElement to add.
+     *
+     */
+    QDomElement domElement(const QString& name, QDomDocument& doc) const;
+
+
+    /**
+     * Gets the name of teapot scene type, stored in g_scene_name.
+     *
+     * @return The name of teapot scene type, stored in g_scene_name.
+     *
+     */
+    const QString& scene_name(void) const {return g_scene_name;}
+
+
+    /// Public static const scene name for the teapot scene.
+    static const QString g_scene_name;
+
+
+private:
+
+
+    /// The wireframe flag.
+    /// true means that the teapot will be draw in wireframe.
+    /// false means that a solid teapot will be drawn.
+    int m_bWireframe;
+
+
+    /// Width of the lines of the teapot.
+    /// The width is specified in pixels.
+    int m_iWidth;
+
+};
+
+
+#endif // __DEFAULT_TEAPOT_SCENE_CONTENT_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.cpp	(revision 4)
@@ -0,0 +1,101 @@
+#include "DefaultTeapotSceneWidget.h"
+
+
+/**
+ * Default constructor.
+ *
+ */
+DefaultTeapotSceneWidget::DefaultTeapotSceneWidget(SceneInterface *plugin, QWidget* pParent, Qt::WFlags flag): SceneWidget(plugin, pParent, flag), m_content(plugin)
+{
+    setupUi (this);
+    updateGUI();
+}
+
+
+/**
+ * Destructor.
+ *
+ */
+DefaultTeapotSceneWidget::~DefaultTeapotSceneWidget()
+{
+}
+
+
+/**
+ * Updates the widget.
+ *
+ * This method can be used it two ways: to force a refresh or to update the
+ * contents of the widget.
+ *
+ * @param content A const pointer on the contents to be used for the widget.
+ *                This contents will be duplicated in the widget. If content
+ *                is NULL, the current contents are used and the refresh is
+ *                forced. If no content is given, NULL is used.
+ *
+ */
+void DefaultTeapotSceneWidget::updateGUI(const SceneContent* _content)
+{
+    if (_content)
+    {
+	const DefaultTeapotSceneContent *content = static_cast<const DefaultTeapotSceneContent*>(_content);
+	Q_ASSERT(NULL!=content); // <-- Assume that the conversion was successful
+	m_content.copy_from(*content);
+    }
+    // From now, we will only use m_content
+    if (m_content.wireframe())
+    {
+	wireframeCheckBox->setCheckState(Qt::Checked);
+	widthSpinBox->setValue(m_content.width());
+    }
+    else
+    {
+	wireframeCheckBox->setCheckState(Qt::Unchecked);
+    }
+}
+
+
+/**
+ * Clears the fields of the widget.
+ *
+ * This method is typically used when the widget will be disabled (if no
+ * channel is specified in Projection Designer, the widget is visible but
+ * disabled: fields must be empty).
+ *
+ */
+void DefaultTeapotSceneWidget::clear(void)
+{
+    widthSpinBox->clear();
+    wireframeCheckBox->setCheckState(Qt::Unchecked);
+}
+
+
+/**
+ * [private slot] Called when the wireframe checkbox state changes.
+ *
+ */
+void DefaultTeapotSceneWidget::on_wireframeCheckBox_stateChanged(int state)
+{
+    bool wireframe=(Qt::Checked==state);
+    widthSpinBox->setEnabled(wireframe);
+    widthLabel->setEnabled(wireframe);
+    if (wireframe!=m_content.wireframe())
+    {
+	m_content.setWireframe(wireframe);
+	emit dataChanged(m_content);
+    }
+}
+
+
+/**
+ * [private slot] Called when the width changes.
+ *
+ */
+void DefaultTeapotSceneWidget::on_widthSpinBox_valueChanged(int width)
+{
+    if (width!=m_content.width())
+    {
+	m_content.setWidth(width);
+	emit dataChanged(m_content);
+    }
+}
+
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/DefaultTeapotSceneWidget.h	(revision 4)
@@ -0,0 +1,118 @@
+#ifndef __DEFAULT_TEAPOT_SCENE_WIDGET_H__
+#define __DEFAULT_TEAPOT_SCENE_WIDGET_H__
+
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes ui_... headers
+#include "ui_defaultteapotscenewidget.h"
+
+// Includes local headers
+#include "DefaultTeapotSceneContent.h"
+
+
+/**
+ * This class implements the widget that enables the control of the teapot
+ * scene.
+ *
+ */
+class DefaultTeapotSceneWidget : public SceneWidget,
+				 private Ui::DefaultTeapotSceneWidget
+{
+    Q_OBJECT
+		
+
+public:
+
+
+    /**
+     * Default constructor.
+     *
+     */
+    DefaultTeapotSceneWidget(SceneInterface *plugin, QWidget* pParent=0, Qt::WFlags flag=0);
+
+
+    /**
+     * Destructor.
+     *
+     */
+    ~DefaultTeapotSceneWidget();
+
+
+    /**
+     * Updates the widget.
+     *
+     * This method can be used it two ways: to force a refresh or to update the
+     * contents of the widget.
+     *
+     * @param content A const pointer on the contents to be used for the widget.
+     *                This contents will be duplicated in the widget. If content
+     *                is NULL, the current contents are used and the refresh is
+     *                forced. If no content is given, NULL is used.
+     *
+     */
+    void updateGUI(const SceneContent* data=NULL);
+
+
+    /**
+     * Clears the fields of the widget.
+     *
+     * This method is typically used when the widget will be disabled (if no
+     * channel is specified in Projection Designer, the widget is visible but
+     * disabled: fields must be empty).
+     *
+     */
+    void clear(void);
+
+
+    /**
+     * Gets the widget contents.
+     *
+     * @return A const reference on the contents of the widget.
+     *
+     */
+    const SceneContent& content(void) const {return m_content;}
+
+
+signals:
+
+
+    /**
+     * [signal] Notify that the contents of the widget have changed.
+     *
+     * This signal is emitted each time that a field is changed.
+     *
+     * @param content A const reference on the new contents (the same as
+     *                returned by the content() method).
+     *
+     */
+    virtual void dataChanged(const SceneContent& content);
+
+
+private slots:
+
+
+    /**
+     * [private slot] Called when the wireframe checkbox state changes.
+     *
+     */
+    void on_wireframeCheckBox_stateChanged(int state);
+
+
+    /**
+     * [private slot] Called when the width changes.
+     *
+     */
+    void on_widthSpinBox_valueChanged(int width);
+
+
+private:
+
+
+    /// The current DefaultPluginData of the widget.
+    DefaultTeapotSceneContent m_content;
+
+};
+
+#endif // __DEFAULT_TEAPOT_SCENE_WIDGET_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultcubemapscenewidget.ui
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultcubemapscenewidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultcubemapscenewidget.ui	(revision 4)
@@ -0,0 +1,250 @@
+<ui version="4.0" >
+ <class>DefaultCubemapSceneWidget</class>
+ <widget class="QWidget" name="DefaultCubemapSceneWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>141</width>
+    <height>279</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="0" column="0" >
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Cubemap Properties</string>
+     </property>
+     <layout class="QGridLayout" >
+      <property name="margin" >
+       <number>9</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item row="0" column="0" >
+       <layout class="QGridLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item row="4" column="1" >
+         <widget class="QLineEdit" name="topFileNameEdit" />
+        </item>
+        <item row="0" column="1" >
+         <widget class="QLineEdit" name="frontFileNameEdit" />
+        </item>
+        <item row="1" column="2" >
+         <widget class="QPushButton" name="backBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1" >
+         <widget class="QLineEdit" name="backFileNameEdit" />
+        </item>
+        <item row="5" column="0" >
+         <widget class="QLabel" name="bottomLabel" >
+          <property name="text" >
+           <string>Bottom</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="2" >
+         <widget class="QPushButton" name="frontBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0" >
+         <widget class="QLabel" name="leftLabel" >
+          <property name="text" >
+           <string>Left</string>
+          </property>
+         </widget>
+        </item>
+        <item row="4" column="2" >
+         <widget class="QPushButton" name="topBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="5" column="1" >
+         <widget class="QLineEdit" name="bottomFileNameEdit" />
+        </item>
+        <item row="4" column="0" >
+         <widget class="QLabel" name="topLabel" >
+          <property name="text" >
+           <string>Top</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="2" >
+         <widget class="QPushButton" name="rightBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="5" column="2" >
+         <widget class="QPushButton" name="bottomBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="0" >
+         <widget class="QLabel" name="rightLabel" >
+          <property name="text" >
+           <string>Right</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="2" >
+         <widget class="QPushButton" name="leftBrowseButton" >
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize" >
+           <size>
+            <width>23</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="text" >
+           <string>...</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="0" >
+         <widget class="QLabel" name="frontLabel" >
+          <property name="text" >
+           <string>Front</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="1" >
+         <widget class="QLineEdit" name="rightFileNameEdit" />
+        </item>
+        <item row="2" column="1" >
+         <widget class="QLineEdit" name="leftFileNameEdit" />
+        </item>
+        <item row="1" column="0" >
+         <widget class="QLabel" name="backLabel" >
+          <property name="text" >
+           <string>Back</string>
+          </property>
+         </widget>
+        </item>
+        <item row="6" column="1" >
+         <spacer>
+          <property name="orientation" >
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" >
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultemptyscenewidget.ui
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultemptyscenewidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultemptyscenewidget.ui	(revision 4)
@@ -0,0 +1,51 @@
+<ui version="4.0" >
+ <class>DefaultEmptySceneWidget</class>
+ <widget class="QWidget" name="DefaultEmptySceneWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>164</width>
+    <height>141</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Empty Properties</string>
+     </property>
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>9</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class="QLabel" name="label" >
+        <property name="text" >
+         <string>(nothing, sorry!)</string>
+        </property>
+        <property name="alignment" >
+         <set>Qt::AlignCenter</set>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultmodelscenewidget.ui
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultmodelscenewidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultmodelscenewidget.ui	(revision 4)
@@ -0,0 +1,119 @@
+<ui version="4.0" >
+ <class>DefaultModelSceneWidget</class>
+ <widget class="QWidget" name="DefaultModelSceneWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>179</width>
+    <height>159</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>0</number>
+   </property>
+   <item row="0" column="0" >
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Model Properties</string>
+     </property>
+     <layout class="QGridLayout" >
+      <property name="margin" >
+       <number>9</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item row="0" column="0" >
+       <layout class="QVBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="modelFileNameLabel" >
+            <property name="text" >
+             <string>File</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="modelFileNameEdit" />
+          </item>
+          <item>
+           <widget class="QPushButton" name="modelBrowseButton" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>0</hsizetype>
+              <vsizetype>0</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize" >
+             <size>
+              <width>23</width>
+              <height>16777215</height>
+             </size>
+            </property>
+            <property name="text" >
+             <string>...</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="modelCullingCheckBox" >
+          <property name="text" >
+           <string>Back face culling</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="modelSmoothingCheckBox" >
+          <property name="text" >
+           <string>Smoothing</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer>
+          <property name="orientation" >
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" >
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.cpp
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.cpp	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.cpp	(revision 4)
@@ -0,0 +1,143 @@
+#include <QtGui>
+#include "defaultplugin.h"
+
+/**
+ * Default constructor of the DefaultPlugin class.
+ *
+ * This constructor should be called just one time, by Qt mechanisms
+ * (not manually).
+ *
+ */
+DefaultPlugin::DefaultPlugin(): QObject()
+{
+}
+
+
+/**
+ * DefaultPlugin destructor.
+ *
+ * This destructor, just like the constructor, is not called manually.
+ *
+ */
+DefaultPlugin::~DefaultPlugin()
+{
+}
+
+
+/**
+ * Gets the name of the Interface (ie. the public name of the plugin).
+ *
+ * @return The name of the Interface (ie. the public name of the plugin).
+ *
+ */
+QString DefaultPlugin::name() const
+{
+    return QString (tr("Default Plugin"));
+}
+
+
+/**
+ * Gets the list of the projectors implemented by the DefaultPlugin.
+ *
+ * @return The list of the projectors implemented by the DefaultPlugin.
+ *
+ */
+QStringList DefaultPlugin::projectors() const
+{
+    return QStringList(DefaultPluginData::g_projector_name);
+}
+
+
+/**
+ * Gets a new ProjectorWidget for a projector.
+ *
+ * @remark The responsability is transfered to the user, especially the
+ *         responsability to delete the widget at the end of use.
+ *
+ * @param projector The name of a projector, from the projectors()-list.
+ *
+ * @return A pointer on the ProjectorWidget.
+ *
+ */
+ProjectorWidget* DefaultPlugin::newProjectorWidget(const QString& projector)
+{
+    if (projector!=DefaultPluginData::g_projector_name) return NULL;
+    return new DefaultProjectorWidget(this);
+}
+
+
+/**
+ * Gets a new ProjectorData for a projector.
+ *
+ * @remark The responsability is transfered to the user, especially the
+ *         responsability to delete the data at the end of use.
+ *
+ * @param projector The name of a projector, from the projectors()-list.
+ *
+ * @return A pointer on the ProjectorData.
+ *
+ */
+ProjectorData *DefaultPlugin::newProjectorData(const QString& projector)
+{
+    if (projector!=DefaultPluginData::g_projector_name) 
+    {
+	return NULL;
+    }
+    return new DefaultPluginData(this);
+}
+
+
+/**
+ * Gets the list of the scenes implemented by the DefaultPlugin.
+ *
+ * @return The list of the scenes implemented by the DefaultPlugin.
+ *
+ */
+QStringList DefaultPlugin::scenes() const
+{
+    return QStringList() << DefaultEmptySceneContent::g_scene_name << DefaultTeapotSceneContent::g_scene_name << DefaultCubemapSceneContent::g_scene_name << DefaultModelSceneContent::g_scene_name;
+}
+
+
+/**
+ * Gets a new SceneWidget for a scene.
+ *
+ * @remark The responsability is transfered to the user, especially the
+ *         responsability to delete the widget at the end of use.
+ *
+ * @param scene_name The name of a scene, from the scenes()-list.
+ *
+ * @return A pointer on the SceneWidget.
+ *
+ */
+SceneContent* DefaultPlugin::newSceneContent(const QString& scene_name)
+{
+    if (scene_name==DefaultEmptySceneContent::g_scene_name) return new DefaultEmptySceneContent(this);
+    else if (scene_name==DefaultTeapotSceneContent::g_scene_name) return new DefaultTeapotSceneContent(this);
+    else if (scene_name==DefaultCubemapSceneContent::g_scene_name) return new DefaultCubemapSceneContent(this);
+    else if (scene_name==DefaultModelSceneContent::g_scene_name) return new DefaultModelSceneContent(this);
+    else return NULL;
+}
+
+/**
+ * Gets a new SceneContent for a scene.
+ *
+ * @remark The responsability is transfered to the user, especially the
+ *         responsability to delete the content at the end of use.
+ *
+ * @param scene The name of a scene, from the scenes()-list.
+ *
+ * @return A pointer on the SceneContent.
+ *
+ */
+SceneWidget* DefaultPlugin::newSceneWidget(const QString& scene_name)
+{
+    if (scene_name==DefaultEmptySceneContent::g_scene_name) return new DefaultEmptySceneWidget(this);
+    else if (scene_name==DefaultTeapotSceneContent::g_scene_name) return new DefaultTeapotSceneWidget(this);
+    else if (scene_name==DefaultCubemapSceneContent::g_scene_name) return new DefaultCubemapSceneWidget(this);
+    else if (scene_name==DefaultModelSceneContent::g_scene_name) return new DefaultModelSceneWidget(this);
+    else return NULL;
+}
+
+
+Q_EXPORT_PLUGIN2(projdesigner_default, DefaultPlugin)
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.h	(revision 4)
@@ -0,0 +1,138 @@
+#ifndef __DEFAULTPLUGIN_H__
+#define __DEFAULTPLUGIN_H__
+
+// Includes Qt headers
+#include <QObject>
+
+// Includes Projection Designer headers
+#include <projdesigner/include/interfaces.h>
+
+// Includes local headers
+#include "DefaultProjectorWidget.h"
+#include "DefaultEmptySceneWidget.h"
+#include "DefaultTeapotSceneWidget.h"
+#include "DefaultCubemapSceneWidget.h"
+#include "DefaultModelSceneWidget.h"
+
+
+/**
+ * DefaultPlugin class implementation.
+ *
+ * This class is the main class of the plugin, the one which implements the
+ * ...Interfaces.
+ *
+ */
+class DefaultPlugin : public QObject,
+		      public ProjectorInterface,
+		      public SceneInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(ProjectorInterface SceneInterface)
+
+public:
+
+
+    /**
+     * Default constructor of the DefaultPlugin class.
+     *
+     * This constructor should be called just one time, by Qt mechanisms
+     * (not manually).
+     *
+     */
+    DefaultPlugin();
+
+
+    /**
+     * DefaultPlugin destructor.
+     *
+     * This destructor, just like the constructor, is not called manually.
+     *
+     */
+    ~DefaultPlugin();
+
+
+    /**
+     * Gets the name of the Interface (ie. the public name of the plugin).
+     *
+     * @return The name of the Interface (ie. the public name of the plugin).
+     *
+     */
+    QString name() const;
+
+
+    /**
+     * Gets the list of the projectors implemented by the DefaultPlugin.
+     *
+     * @return The list of the projectors implemented by the DefaultPlugin.
+     *
+     */
+    QStringList projectors() const;
+
+
+    /**
+     * Gets a new ProjectorWidget for a projector.
+     *
+     * @remark The responsability is transfered to the user, especially the
+     *         responsability to delete the widget at the end of use.
+     *
+     * @param projector The name of a projector, from the projectors()-list.
+     *
+     * @return A pointer on the ProjectorWidget.
+     *
+     */
+    ProjectorWidget* newProjectorWidget(const QString& projector);
+
+
+    /**
+     * Gets a new ProjectorData for a projector.
+     *
+     * @remark The responsability is transfered to the user, especially the
+     *         responsability to delete the data at the end of use.
+     *
+     * @param projector The name of a projector, from the projectors()-list.
+     *
+     * @return A pointer on the ProjectorData.
+     *
+     */
+    ProjectorData *newProjectorData(const QString& projector);
+
+
+    /**
+     * Gets the list of the scenes implemented by the DefaultPlugin.
+     *
+     * @return The list of the scenes implemented by the DefaultPlugin.
+     *
+     */
+    QStringList scenes() const;
+
+
+    /**
+     * Gets a new SceneWidget for a scene.
+     *
+     * @remark The responsability is transfered to the user, especially the
+     *         responsability to delete the widget at the end of use.
+     *
+     * @param scene_name The name of a scene, from the scenes()-list.
+     *
+     * @return A pointer on the SceneWidget.
+     *
+     */
+    SceneWidget* newSceneWidget(const QString& scene_name);
+
+
+    /**
+     * Gets a new SceneContent for a scene.
+     *
+     * @remark The responsability is transfered to the user, especially the
+     *         responsability to delete the content at the end of use.
+     *
+     * @param scene The name of a scene, from the scenes()-list.
+     *
+     * @return A pointer on the SceneContent.
+     *
+     */
+    SceneContent* newSceneContent(const QString& scene_name);
+
+};
+
+#endif // __DEFAULTPLUGIN_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.pro
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.pro	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.pro	(revision 4)
@@ -0,0 +1,40 @@
+TEMPLATE      = lib
+QT           += opengl xml
+CONFIG       += plugin static
+INCLUDEPATH  += ../..
+
+HEADERS += defaultplugin.h
+HEADERS += DefaultProjectorWidget.h
+HEADERS += DefaultProjectorData.h
+HEADERS += DefaultEmptySceneContent.h
+HEADERS += DefaultEmptySceneWidget.h
+HEADERS += DefaultTeapotSceneContent.h
+HEADERS += DefaultTeapotSceneWidget.h
+HEADERS += DefaultCubemapSceneContent.h
+HEADERS += DefaultCubemapSceneWidget.h
+HEADERS += DefaultModelSceneContent.h
+HEADERS += DefaultModelSceneWidget.h
+HEADERS += glm.h
+
+SOURCES += defaultplugin.cpp
+SOURCES += DefaultProjectorWidget.cpp
+SOURCES += DefaultProjectorData.cpp
+SOURCES += DefaultEmptySceneContent.cpp
+SOURCES += DefaultEmptySceneWidget.cpp
+SOURCES += DefaultTeapotSceneContent.cpp
+SOURCES += DefaultTeapotSceneWidget.cpp
+SOURCES += DefaultCubemapSceneContent.cpp
+SOURCES += DefaultCubemapSceneWidget.cpp
+SOURCES += DefaultModelSceneContent.cpp
+SOURCES += DefaultModelSceneWidget.cpp
+SOURCES += glm.c
+
+FORMS += defaultprojectorwidget.ui
+FORMS += defaultemptyscenewidget.ui
+FORMS += defaultteapotscenewidget.ui
+FORMS += defaultcubemapscenewidget.ui
+FORMS += defaultmodelscenewidget.ui
+
+TARGET        = projdesigner_default
+
+win32:DESTDIR = ./
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.vcproj
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.vcproj	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultplugin.vcproj	(revision 4)
@@ -0,0 +1,1060 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="projdesigner_default"
+	ProjectGUID="{4515EF56-8947-4D65-A33D-9530D9B33B07}"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="."
+			IntermediateDirectory=".\release"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/I$(QTDIR)\mkspecs\win32-msvc -Zm200 "
+				Optimization="1"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="$(QTDIR)\include\QtCore,$(QTDIR)\include\QtGui,$(QTDIR)\include\QtOpenGL,$(QTDIR)\include\QtXml,$(QTDIR)\include,..\..,$(QTDIR)\include\ActiveQt,release,."
+				PreprocessorDefinitions="_LIB;UNICODE;QT_LARGEFILE_SUPPORT;QT_NO_DEBUG;QT_STATICPLUGIN;QT_PLUGIN;QT_XML_LIB;QT_OPENGL_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;WIN32"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				RuntimeTypeInfo="true"
+				PrecompiledHeaderFile=".\release/defaultplugin.pch"
+				AssemblerListingLocation=".\release/"
+				ObjectFile=".\release/"
+				ProgramDataBaseFileName=".\release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="..\..\projdesigner\plugins\defaultplugin.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="."
+			IntermediateDirectory=".\debug"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/I$(QTDIR)\mkspecs\win32-msvc -Zm200 "
+				Optimization="4"
+				AdditionalIncludeDirectories="$(QTDIR)\include\QtCore,$(QTDIR)\include\QtGui,$(QTDIR)\include\QtOpenGL,$(QTDIR)\include\QtXml,$(QTDIR)\include,..\..,$(QTDIR)\include\ActiveQt,debug,."
+				PreprocessorDefinitions="_LIB;UNICODE;QT_LARGEFILE_SUPPORT;QT_STATICPLUGIN;QT_PLUGIN;QT_XML_LIB;QT_OPENGL_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;WIN32"
+				RuntimeLibrary="3"
+				RuntimeTypeInfo="true"
+				PrecompiledHeaderFile=".\debug/defaultplugin.pch"
+				AssemblerListingLocation=".\debug/"
+				ObjectFile=".\debug/"
+				ProgramDataBaseFileName=".\debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="..\..\projdesigner\plugins\defaultplugind.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+			>
+			<File
+				RelativePath="DefaultCubemapSceneContent.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultCubemapSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneContent.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneContent.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultplugin.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultProjectorData.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultProjectorWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneContent.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="glm.c"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl"
+			>
+			<File
+				RelativePath="DefaultCubemapSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultCubemapSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultCubemapSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultCubemapSceneWidget.h&quot; -o &quot;release\moc_DefaultCubemapSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_DefaultCubemapSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultCubemapSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultCubemapSceneWidget.h&quot; -o &quot;debug\moc_DefaultCubemapSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_DefaultCubemapSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultEmptySceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultEmptySceneWidget.h&quot; -o &quot;release\moc_DefaultEmptySceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_DefaultEmptySceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultEmptySceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultEmptySceneWidget.h&quot; -o &quot;debug\moc_DefaultEmptySceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_DefaultEmptySceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultModelSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultModelSceneWidget.h&quot; -o &quot;release\moc_DefaultModelSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_DefaultModelSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultModelSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultModelSceneWidget.h&quot; -o &quot;debug\moc_DefaultModelSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_DefaultModelSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultplugin.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on defaultplugin.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;defaultplugin.h&quot; -o &quot;release\moc_defaultplugin.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_defaultplugin.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on defaultplugin.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;defaultplugin.h&quot; -o &quot;debug\moc_defaultplugin.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_defaultplugin.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultProjectorData.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultProjectorWidget.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultProjectorWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultProjectorWidget.h&quot; -o &quot;release\moc_DefaultProjectorWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_DefaultProjectorWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultProjectorWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultProjectorWidget.h&quot; -o &quot;debug\moc_DefaultProjectorWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_DefaultProjectorWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultTeapotSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\release&quot; -I&quot;.&quot; &quot;DefaultTeapotSceneWidget.h&quot; -o &quot;release\moc_DefaultTeapotSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="release\moc_DefaultTeapotSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running MOC on DefaultTeapotSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe -D_LIB -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -DWIN32 -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;.\..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;.\debug&quot; -I&quot;.&quot; &quot;DefaultTeapotSceneWidget.h&quot; -o &quot;debug\moc_DefaultTeapotSceneWidget.cpp&quot;&#x0D;&#x0A;"
+						Outputs="debug\moc_DefaultTeapotSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="glm.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Form Files"
+			Filter="ui"
+			>
+			<File
+				RelativePath="defaultcubemapscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultcubemapscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultcubemapscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultcubemapscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultcubemapscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultcubemapscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultcubemapscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultemptyscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultemptyscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultemptyscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultemptyscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultemptyscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultemptyscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultemptyscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultmodelscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultmodelscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultmodelscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultmodelscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultmodelscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultmodelscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultmodelscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultprojectorwidget.ui"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultprojectorwidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultprojectorwidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultprojectorwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultprojectorwidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultprojectorwidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultprojectorwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultteapotscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultteapotscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultteapotscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultteapotscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="Running UIC on defaultteapotscenewidget.ui"
+						CommandLine="&quot;$(QTDIR)&quot;\bin\uic.exe &quot;$(InputPath)&quot; -o .\ui_defaultteapotscenewidget.h&#x0D;&#x0A;"
+						Outputs=".\ui_defaultteapotscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Generated"
+			>
+			<File
+				RelativePath="debug\moc_DefaultCubemapSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultCubemapSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultEmptySceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultEmptySceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultModelSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultModelSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_defaultplugin.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_defaultplugin.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultProjectorWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultProjectorWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultTeapotSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultTeapotSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						Optimization="1"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="ui_defaultcubemapscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultemptyscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultmodelscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultprojectorwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultteapotscenewidget.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultprojectorwidget.ui
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultprojectorwidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultprojectorwidget.ui	(revision 4)
@@ -0,0 +1,154 @@
+<ui version="4.0" >
+ <class>DefaultProjectorWidget</class>
+ <widget class="QWidget" name="DefaultProjectorWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>164</width>
+    <height>141</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Projection</string>
+     </property>
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="margin" >
+         <number>4</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="fovLabel" >
+            <property name="text" >
+             <string>FOV</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="fovEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="aspectLabel" >
+            <property name="text" >
+             <string>Aspect</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="aspectRatioEdit" />
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="nearLabel" >
+            <property name="text" >
+             <string>Near</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="nearEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="farLabel" >
+            <property name="text" >
+             <string>Far</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="farEdit" />
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="offaxisLabel" >
+            <property name="text" >
+             <string>Off-axis </string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLabel" name="offaxisXLabel" >
+            <property name="text" >
+             <string>X</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="offaxisXEdit" />
+          </item>
+          <item>
+           <widget class="QLabel" name="offaxisYLabel" >
+            <property name="text" >
+             <string>Y</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="offaxisYEdit" />
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>fovEdit</tabstop>
+  <tabstop>aspectRatioEdit</tabstop>
+  <tabstop>nearEdit</tabstop>
+  <tabstop>farEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultteapotscenewidget.ui
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultteapotscenewidget.ui	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/defaultteapotscenewidget.ui	(revision 4)
@@ -0,0 +1,114 @@
+<ui version="4.0" >
+ <class>DefaultTeapotSceneWidget</class>
+ <widget class="QWidget" name="DefaultTeapotSceneWidget" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>227</width>
+    <height>79</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Projection Settings</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <property name="spacing" >
+    <number>0</number>
+   </property>
+   <item row="0" column="0" >
+    <widget class="QGroupBox" name="projectionGroup" >
+     <property name="title" >
+      <string>Teapot Properties</string>
+     </property>
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>9</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QCheckBox" name="wireframeCheckBox" >
+          <property name="text" >
+           <string>Wireframe</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="widthLabel" >
+          <property name="text" >
+           <string>Width</string>
+          </property>
+          <property name="alignment" >
+           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="widthSpinBox" >
+          <property name="suffix" >
+           <string> px</string>
+          </property>
+          <property name="maximum" >
+           <number>10</number>
+          </property>
+          <property name="minimum" >
+           <number>1</number>
+          </property>
+          <property name="value" >
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer>
+        <property name="orientation" >
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" >
+         <size>
+          <width>20</width>
+          <height>40</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>widthLabel</sender>
+   <signal>linkActivated(QString)</signal>
+   <receiver>widthSpinBox</receiver>
+   <slot>selectAll()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>114</x>
+     <y>44</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>171</x>
+     <y>47</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.c
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.c	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.c	(revision 4)
@@ -0,0 +1,1910 @@
+/*    
+      glm.c
+      Nate Robins, 1997, 2000
+      nate@pobox.com, http://www.pobox.com/~nate
+ 
+      Wavefront OBJ model file format reader/writer/manipulator.
+
+      Includes routines for generating smooth normals with
+      preservation of edges, welding redundant vertices & texture
+      coordinate generation (spheremap and planar projections) + more.
+  
+*/
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "glm.h"
+
+
+#define T(x) (model->triangles[(x)])
+
+
+/* _GLMnode: general purpose node */
+typedef struct _GLMnode {
+    GLuint         index;
+    GLboolean      averaged;
+    struct _GLMnode* next;
+} GLMnode;
+
+
+/* glmMax: returns the maximum of two floats */
+static GLfloat
+glmMax(GLfloat a, GLfloat b) 
+{
+    if (b > a)
+        return b;
+    return a;
+}
+
+/* glmAbs: returns the absolute value of a float */
+static GLfloat
+glmAbs(GLfloat f)
+{
+    if (f < 0)
+        return -f;
+    return f;
+}
+
+/* glmDot: compute the dot product of two vectors
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3])
+ */
+static GLfloat
+glmDot(GLfloat* u, GLfloat* v)
+{
+    assert(u); assert(v);
+    
+    return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
+}
+
+/* glmCross: compute the cross product of two vectors
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3])
+ * n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in
+ */
+static GLvoid
+glmCross(GLfloat* u, GLfloat* v, GLfloat* n)
+{
+    assert(u); assert(v); assert(n);
+    
+    n[0] = u[1]*v[2] - u[2]*v[1];
+    n[1] = u[2]*v[0] - u[0]*v[2];
+    n[2] = u[0]*v[1] - u[1]*v[0];
+}
+
+/* glmNormalize: normalize a vector
+ *
+ * v - array of 3 GLfloats (GLfloat v[3]) to be normalized
+ */
+static GLvoid
+glmNormalize(GLfloat* v)
+{
+    GLfloat l;
+    
+    assert(v);
+    
+    l = (GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+    v[0] /= l;
+    v[1] /= l;
+    v[2] /= l;
+}
+
+/* glmEqual: compares two vectors and returns GL_TRUE if they are
+ * equal (within a certain threshold) or GL_FALSE if not. An epsilon
+ * that works fairly well is 0.000001.
+ *
+ * u - array of 3 GLfloats (GLfloat u[3])
+ * v - array of 3 GLfloats (GLfloat v[3]) 
+ */
+static GLboolean
+glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon)
+{
+    if (glmAbs(u[0] - v[0]) < epsilon &&
+        glmAbs(u[1] - v[1]) < epsilon &&
+        glmAbs(u[2] - v[2]) < epsilon) 
+    {
+        return GL_TRUE;
+    }
+    return GL_FALSE;
+}
+
+/* glmWeldVectors: eliminate (weld) vectors that are within an
+ * epsilon of each other.
+ *
+ * vectors     - array of GLfloat[3]'s to be welded
+ * numvectors - number of GLfloat[3]'s in vectors
+ * epsilon     - maximum difference between vectors 
+ *
+ */
+GLfloat*
+glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon)
+{
+    GLfloat* copies;
+    GLuint   copied;
+    GLuint   i, j;
+    
+    copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
+    memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
+    
+    copied = 1;
+    for (i = 1; i <= *numvectors; i++) {
+        for (j = 1; j <= copied; j++) {
+            if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
+                goto duplicate;
+            }
+        }
+        
+        /* must not be any duplicates -- add to the copies array */
+        copies[3 * copied + 0] = vectors[3 * i + 0];
+        copies[3 * copied + 1] = vectors[3 * i + 1];
+        copies[3 * copied + 2] = vectors[3 * i + 2];
+        j = copied;             /* pass this along for below */
+        copied++;
+        
+duplicate:
+/* set the first component of this vector to point at the correct
+        index into the new copies array */
+        vectors[3 * i + 0] = (GLfloat)j;
+    }
+    
+    *numvectors = copied-1;
+    return copies;
+}
+
+/* glmFindGroup: Find a group in the model */
+GLMgroup*
+glmFindGroup(GLMmodel* model, char* name)
+{
+    GLMgroup* group;
+    
+    assert(model);
+    
+    group = model->groups;
+    while(group) {
+        if (!strcmp(name, group->name))
+            break;
+        group = group->next;
+    }
+    
+    return group;
+}
+
+/* glmAddGroup: Add a group to the model */
+GLMgroup*
+glmAddGroup(GLMmodel* model, char* name)
+{
+    GLMgroup* group;
+    
+    group = glmFindGroup(model, name);
+    if (!group) {
+        group = (GLMgroup*)malloc(sizeof(GLMgroup));
+        group->name = _strdup(name);
+        group->material = 0;
+        group->numtriangles = 0;
+        group->triangles = NULL;
+        group->next = model->groups;
+        model->groups = group;
+        model->numgroups++;
+    }
+    
+    return group;
+}
+
+/* glmFindGroup: Find a material in the model */
+GLuint
+glmFindMaterial(GLMmodel* model, char* name)
+{
+    GLuint i;
+    
+    /* XXX doing a linear search on a string key'd list is pretty lame,
+    but it works and is fast enough for now. */
+    for (i = 0; i < model->nummaterials; i++) {
+        if (!strcmp(model->materials[i].name, name))
+            goto found;
+    }
+    
+    /* didn't find the name, so print a warning and return the default
+    material (0). */
+    printf("glmFindMaterial():  can't find material \"%s\".\n", name);
+    i = 0;
+    
+found:
+    return i;
+}
+
+
+/* glmDirName: return the directory given a path
+ *
+ * path - filesystem path
+ *
+ * NOTE: the return value should be free'd.
+ */
+static char*
+glmDirName(char* path)
+{
+    char* dir;
+    char* s;
+    
+    dir = _strdup(path);
+    
+    s = strrchr(dir, '/');
+    if (s)
+        s[1] = '\0';
+    else
+        dir[0] = '\0';
+    
+    return dir;
+}
+
+
+/* glmReadMTL: read a wavefront material library file
+ *
+ * model - properly initialized GLMmodel structure
+ * name  - name of the material library
+ */
+static GLvoid
+glmReadMTL(GLMmodel* model, char* name)
+{
+    FILE* file;
+    char* dir;
+    char* filename;
+    char    buf[128];
+    GLuint nummaterials, i;
+    
+    dir = glmDirName(model->pathname);
+    filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
+    strcpy(filename, dir);
+    strcat(filename, name);
+    free(dir);
+    
+    file = fopen(filename, "r");
+    if (!file) {
+        fprintf(stderr, "glmReadMTL() failed: can't open material file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    free(filename);
+    
+    /* count the number of materials in the file */
+    nummaterials = 1;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'n':               /* newmtl */
+            fgets(buf, sizeof(buf), file);
+            nummaterials++;
+            sscanf(buf, "%s %s", buf, buf);
+            break;
+        default:
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        }
+    }
+    
+    rewind(file);
+    
+    model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
+    model->nummaterials = nummaterials;
+    
+    /* set the default material */
+    for (i = 0; i < nummaterials; i++) {
+        model->materials[i].name = NULL;
+        model->materials[i].shininess = 65.f;
+        model->materials[i].diffuse[0] = 0.8f;
+        model->materials[i].diffuse[1] = 0.8f;
+        model->materials[i].diffuse[2] = 0.8f;
+        model->materials[i].diffuse[3] = 1.0f;
+        model->materials[i].ambient[0] = 0.2f;
+        model->materials[i].ambient[1] = 0.2f;
+        model->materials[i].ambient[2] = 0.2f;
+        model->materials[i].ambient[3] = 1.f;
+        model->materials[i].specular[0] = 0.f;
+        model->materials[i].specular[1] = 0.f;
+        model->materials[i].specular[2] = 0.f;
+        model->materials[i].specular[3] = 1.f;
+    }
+    model->materials[0].name = strdup("default");
+    
+    /* now, read in the data */
+    nummaterials = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'n':               /* newmtl */
+            fgets(buf, sizeof(buf), file);
+            sscanf(buf, "%s %s", buf, buf);
+            nummaterials++;
+            model->materials[nummaterials].name = strdup(buf);
+            break;
+        case 'N':
+            fscanf(file, "%f", &model->materials[nummaterials].shininess);
+            /* wavefront shininess is from [0, 1000], so scale for OpenGL */
+            model->materials[nummaterials].shininess /= 1000.0;
+            model->materials[nummaterials].shininess *= 128.0;
+            break;
+        case 'K':
+            switch(buf[1]) {
+            case 'd':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].diffuse[0],
+                    &model->materials[nummaterials].diffuse[1],
+                    &model->materials[nummaterials].diffuse[2]);
+                break;
+            case 's':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].specular[0],
+                    &model->materials[nummaterials].specular[1],
+                    &model->materials[nummaterials].specular[2]);
+                break;
+            case 'a':
+                fscanf(file, "%f %f %f",
+                    &model->materials[nummaterials].ambient[0],
+                    &model->materials[nummaterials].ambient[1],
+                    &model->materials[nummaterials].ambient[2]);
+                break;
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+            }
+            break;
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+        }
+    }
+
+    fclose(file);
+}
+
+/* glmWriteMTL: write a wavefront material library file
+ *
+ * model   - properly initialized GLMmodel structure
+ * modelpath  - pathname of the model being written
+ * mtllibname - name of the material library to be written
+ */
+static GLvoid
+glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname)
+{
+    FILE* file;
+    char* dir;
+    char* filename;
+    GLMmaterial* material;
+    GLuint i;
+    
+    dir = glmDirName(modelpath);
+    filename = (char*)malloc(sizeof(char) * (strlen(dir)+strlen(mtllibname)));
+    strcpy(filename, dir);
+    strcat(filename, mtllibname);
+    free(dir);
+    
+    /* open the file */
+    file = fopen(filename, "w");
+    if (!file) {
+        fprintf(stderr, "glmWriteMTL() failed: can't open file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    free(filename);
+    
+    /* spit out a header */
+    fprintf(file, "#  \n");
+    fprintf(file, "#  Wavefront MTL generated by GLM library\n");
+    fprintf(file, "#  \n");
+    fprintf(file, "#  GLM library\n");
+    fprintf(file, "#  Nate Robins\n");
+    fprintf(file, "#  ndr@pobox.com\n");
+    fprintf(file, "#  http://www.pobox.com/~ndr\n");
+    fprintf(file, "#  \n\n");
+    
+    for (i = 0; i < model->nummaterials; i++) {
+        material = &model->materials[i];
+        fprintf(file, "newmtl %s\n", material->name);
+        fprintf(file, "Ka %f %f %f\n", 
+            material->ambient[0], material->ambient[1], material->ambient[2]);
+        fprintf(file, "Kd %f %f %f\n", 
+            material->diffuse[0], material->diffuse[1], material->diffuse[2]);
+        fprintf(file, "Ks %f %f %f\n", 
+            material->specular[0],material->specular[1],material->specular[2]);
+        fprintf(file, "Ns %f\n", material->shininess / 128.0 * 1000.0);
+        fprintf(file, "\n");
+    }
+}
+
+
+/* glmFirstPass: first pass at a Wavefront OBJ file that gets all the
+ * statistics of the model (such as #vertices, #normals, etc)
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static GLvoid
+glmFirstPass(GLMmodel* model, FILE* file) 
+{
+    GLuint  numvertices;        /* number of vertices in model */
+    GLuint  numnormals;         /* number of normals in model */
+    GLuint  numtexcoords;       /* number of texcoords in model */
+    GLuint  numtriangles;       /* number of triangles in model */
+    GLMgroup* group;            /* current group */
+    unsigned    v, n, t;
+    char        buf[128];
+    
+    /* make a default group */
+    group = glmAddGroup(model, "default");
+    
+    numvertices = numnormals = numtexcoords = numtriangles = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'v':               /* v, vn, vt */
+            switch(buf[1]) {
+            case '\0':          /* vertex */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numvertices++;
+                break;
+            case 'n':           /* normal */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numnormals++;
+                break;
+            case 't':           /* texcoord */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                numtexcoords++;
+                break;
+            default:
+                printf("glmFirstPass(): Unknown token \"%s\".\n", buf);
+                exit(1);
+                break;
+            }
+            break;
+            case 'm':
+                fgets(buf, sizeof(buf), file);
+                sscanf(buf, "%s %s", buf, buf);
+                model->mtllibname = strdup(buf);
+                glmReadMTL(model, buf);
+                break;
+            case 'u':
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+            case 'g':               /* group */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+#if SINGLE_STRING_GROUP_NAMES
+                sscanf(buf, "%s", buf);
+#else
+                buf[strlen(buf)-1] = '\0';  /* nuke '\n' */
+#endif
+                group = glmAddGroup(model, buf);
+                break;
+            case 'f':               /* face */
+                v = n = t = 0;
+                fscanf(file, "%s", buf);
+                /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+                if (strstr(buf, "//")) {
+                    /* v//n */
+                    sscanf(buf, "%d//%d", &v, &n);
+                    fscanf(file, "%d//%d", &v, &n);
+                    fscanf(file, "%d//%d", &v, &n);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d//%d", &v, &n) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
+                    /* v/t/n */
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+                    /* v/t */
+                    fscanf(file, "%d/%d", &v, &t);
+                    fscanf(file, "%d/%d", &v, &t);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d/%d", &v, &t) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                } else {
+                    /* v */
+                    fscanf(file, "%d", &v);
+                    fscanf(file, "%d", &v);
+                    numtriangles++;
+                    group->numtriangles++;
+                    while(fscanf(file, "%d", &v) > 0) {
+                        numtriangles++;
+                        group->numtriangles++;
+                    }
+                }
+                break;
+                
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+        }
+  }
+  
+  /* set the stats in the model structure */
+  model->numvertices  = numvertices;
+  model->numnormals   = numnormals;
+  model->numtexcoords = numtexcoords;
+  model->numtriangles = numtriangles;
+  
+  /* allocate memory for the triangles in each group */
+  group = model->groups;
+  while(group) {
+      group->triangles = (GLuint*)malloc(sizeof(GLuint) * group->numtriangles);
+      group->numtriangles = 0;
+      group = group->next;
+  }
+}
+
+/* glmSecondPass: second pass at a Wavefront OBJ file that gets all
+ * the data.
+ *
+ * model - properly initialized GLMmodel structure
+ * file  - (fopen'd) file descriptor 
+ */
+static GLvoid
+glmSecondPass(GLMmodel* model, FILE* file) 
+{
+    GLuint  numvertices;        /* number of vertices in model */
+    GLuint  numnormals;         /* number of normals in model */
+    GLuint  numtexcoords;       /* number of texcoords in model */
+    GLuint  numtriangles;       /* number of triangles in model */
+    GLfloat*    vertices;           /* array of vertices  */
+    GLfloat*    normals;            /* array of normals */
+    GLfloat*    texcoords;          /* array of texture coordinates */
+    GLMgroup* group;            /* current group pointer */
+    GLuint  material;           /* current material */
+    GLuint  v, n, t;
+    char        buf[128];
+    
+    /* set the pointer shortcuts */
+    vertices       = model->vertices;
+    normals    = model->normals;
+    texcoords    = model->texcoords;
+    group      = model->groups;
+    
+    /* on the second pass through the file, read all the data into the
+    allocated arrays */
+    numvertices = numnormals = numtexcoords = 1;
+    numtriangles = 0;
+    material = 0;
+    while(fscanf(file, "%s", buf) != EOF) {
+        switch(buf[0]) {
+        case '#':               /* comment */
+            /* eat up rest of line */
+            fgets(buf, sizeof(buf), file);
+            break;
+        case 'v':               /* v, vn, vt */
+            switch(buf[1]) {
+            case '\0':          /* vertex */
+                fscanf(file, "%f %f %f", 
+                    &vertices[3 * numvertices + 0], 
+                    &vertices[3 * numvertices + 1], 
+                    &vertices[3 * numvertices + 2]);
+                numvertices++;
+                break;
+            case 'n':           /* normal */
+                fscanf(file, "%f %f %f", 
+                    &normals[3 * numnormals + 0],
+                    &normals[3 * numnormals + 1], 
+                    &normals[3 * numnormals + 2]);
+                numnormals++;
+                break;
+            case 't':           /* texcoord */
+                fscanf(file, "%f %f", 
+                    &texcoords[2 * numtexcoords + 0],
+                    &texcoords[2 * numtexcoords + 1]);
+                numtexcoords++;
+                break;
+            }
+            break;
+            case 'u':
+                fgets(buf, sizeof(buf), file);
+                sscanf(buf, "%s %s", buf, buf);
+                group->material = material = glmFindMaterial(model, buf);
+                break;
+            case 'g':               /* group */
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+#if SINGLE_STRING_GROUP_NAMES
+                sscanf(buf, "%s", buf);
+#else
+                buf[strlen(buf)-1] = '\0';  /* nuke '\n' */
+#endif
+                group = glmFindGroup(model, buf);
+                group->material = material;
+                break;
+            case 'f':               /* face */
+                v = n = t = 0;
+                fscanf(file, "%s", buf);
+                /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
+                if (strstr(buf, "//")) {
+                    /* v//n */
+                    sscanf(buf, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).nindices[0] = n;
+                    fscanf(file, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).nindices[1] = n;
+                    fscanf(file, "%d//%d", &v, &n);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).nindices[2] = n;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d//%d", &v, &n) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).nindices[2] = n;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
+                    /* v/t/n */
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).tindices[0] = t;
+                    T(numtriangles).nindices[0] = n;
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).tindices[1] = t;
+                    T(numtriangles).nindices[1] = n;
+                    fscanf(file, "%d/%d/%d", &v, &t, &n);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).tindices[2] = t;
+                    T(numtriangles).nindices[2] = n;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+                        T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+                        T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).tindices[2] = t;
+                        T(numtriangles).nindices[2] = n;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
+                    /* v/t */
+                    T(numtriangles).vindices[0] = v;
+                    T(numtriangles).tindices[0] = t;
+                    fscanf(file, "%d/%d", &v, &t);
+                    T(numtriangles).vindices[1] = v;
+                    T(numtriangles).tindices[1] = t;
+                    fscanf(file, "%d/%d", &v, &t);
+                    T(numtriangles).vindices[2] = v;
+                    T(numtriangles).tindices[2] = t;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d/%d", &v, &t) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        T(numtriangles).tindices[2] = t;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                } else {
+                    /* v */
+                    sscanf(buf, "%d", &v);
+                    T(numtriangles).vindices[0] = v;
+                    fscanf(file, "%d", &v);
+                    T(numtriangles).vindices[1] = v;
+                    fscanf(file, "%d", &v);
+                    T(numtriangles).vindices[2] = v;
+                    group->triangles[group->numtriangles++] = numtriangles;
+                    numtriangles++;
+                    while(fscanf(file, "%d", &v) > 0) {
+                        T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
+                        T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
+                        T(numtriangles).vindices[2] = v;
+                        group->triangles[group->numtriangles++] = numtriangles;
+                        numtriangles++;
+                    }
+                }
+                break;
+                
+            default:
+                /* eat up rest of line */
+                fgets(buf, sizeof(buf), file);
+                break;
+    }
+  }
+  
+#if 0
+  /* announce the memory requirements */
+  printf(" Memory: %d bytes\n",
+      numvertices  * 3*sizeof(GLfloat) +
+      numnormals   * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) +
+      numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) +
+      numtriangles * sizeof(GLMtriangle));
+#endif
+}
+
+
+/* public functions */
+
+
+/* glmUnitize: "unitize" a model by translating it to the origin and
+ * scaling it to fit in a unit cube around the origin.   Returns the
+ * scalefactor used.
+ *
+ * model - properly initialized GLMmodel structure 
+ */
+GLfloat
+glmUnitize(GLMmodel* model)
+{
+    GLuint  i;
+    GLfloat maxx, minx, maxy, miny, maxz, minz;
+    GLfloat cx, cy, cz, w, h, d;
+    GLfloat scale;
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* get the max/mins */
+    maxx = minx = model->vertices[3 + 0];
+    maxy = miny = model->vertices[3 + 1];
+    maxz = minz = model->vertices[3 + 2];
+    for (i = 1; i <= model->numvertices; i++) {
+        if (maxx < model->vertices[3 * i + 0])
+            maxx = model->vertices[3 * i + 0];
+        if (minx > model->vertices[3 * i + 0])
+            minx = model->vertices[3 * i + 0];
+        
+        if (maxy < model->vertices[3 * i + 1])
+            maxy = model->vertices[3 * i + 1];
+        if (miny > model->vertices[3 * i + 1])
+            miny = model->vertices[3 * i + 1];
+        
+        if (maxz < model->vertices[3 * i + 2])
+            maxz = model->vertices[3 * i + 2];
+        if (minz > model->vertices[3 * i + 2])
+            minz = model->vertices[3 * i + 2];
+    }
+    
+    /* calculate model width, height, and depth */
+    w = glmAbs(maxx) + glmAbs(minx);
+    h = glmAbs(maxy) + glmAbs(miny);
+    d = glmAbs(maxz) + glmAbs(minz);
+    
+    /* calculate center of the model */
+    cx = (maxx + minx) / 2.0;
+    cy = (maxy + miny) / 2.0;
+    cz = (maxz + minz) / 2.0;
+    
+    /* calculate unitizing scale factor */
+    scale = 2.0 / glmMax(glmMax(w, h), d);
+    
+    /* translate around center then scale */
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] -= cx;
+        model->vertices[3 * i + 1] -= cy;
+        model->vertices[3 * i + 2] -= cz;
+        model->vertices[3 * i + 0] *= scale;
+        model->vertices[3 * i + 1] *= scale;
+        model->vertices[3 * i + 2] *= scale;
+    }
+    
+    return scale;
+}
+
+/* glmDimensions: Calculates the dimensions (width, height, depth) of
+ * a model.
+ *
+ * model   - initialized GLMmodel structure
+ * dimensions - array of 3 GLfloats (GLfloat dimensions[3])
+ */
+GLvoid
+glmDimensions(GLMmodel* model, GLfloat* dimensions)
+{
+    GLuint i;
+    GLfloat maxx, minx, maxy, miny, maxz, minz;
+    
+    assert(model);
+    assert(model->vertices);
+    assert(dimensions);
+    
+    /* get the max/mins */
+    maxx = minx = model->vertices[3 + 0];
+    maxy = miny = model->vertices[3 + 1];
+    maxz = minz = model->vertices[3 + 2];
+    for (i = 1; i <= model->numvertices; i++) {
+        if (maxx < model->vertices[3 * i + 0])
+            maxx = model->vertices[3 * i + 0];
+        if (minx > model->vertices[3 * i + 0])
+            minx = model->vertices[3 * i + 0];
+        
+        if (maxy < model->vertices[3 * i + 1])
+            maxy = model->vertices[3 * i + 1];
+        if (miny > model->vertices[3 * i + 1])
+            miny = model->vertices[3 * i + 1];
+        
+        if (maxz < model->vertices[3 * i + 2])
+            maxz = model->vertices[3 * i + 2];
+        if (minz > model->vertices[3 * i + 2])
+            minz = model->vertices[3 * i + 2];
+    }
+    
+    /* calculate model width, height, and depth */
+    dimensions[0] = glmAbs(maxx) + glmAbs(minx);
+    dimensions[1] = glmAbs(maxy) + glmAbs(miny);
+    dimensions[2] = glmAbs(maxz) + glmAbs(minz);
+}
+
+/* glmScale: Scales a model by a given amount.
+ * 
+ * model - properly initialized GLMmodel structure
+ * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+ */
+GLvoid
+glmScale(GLMmodel* model, GLfloat scale)
+{
+    GLuint i;
+    
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] *= scale;
+        model->vertices[3 * i + 1] *= scale;
+        model->vertices[3 * i + 2] *= scale;
+    }
+}
+
+/* glmReverseWinding: Reverse the polygon winding for all polygons in
+ * this model.   Default winding is counter-clockwise.  Also changes
+ * the direction of the normals.
+ * 
+ * model - properly initialized GLMmodel structure 
+ */
+GLvoid
+glmReverseWinding(GLMmodel* model)
+{
+    GLuint i, swap;
+    
+    assert(model);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        swap = T(i).vindices[0];
+        T(i).vindices[0] = T(i).vindices[2];
+        T(i).vindices[2] = swap;
+        
+        if (model->numnormals) {
+            swap = T(i).nindices[0];
+            T(i).nindices[0] = T(i).nindices[2];
+            T(i).nindices[2] = swap;
+        }
+        
+        if (model->numtexcoords) {
+            swap = T(i).tindices[0];
+            T(i).tindices[0] = T(i).tindices[2];
+            T(i).tindices[2] = swap;
+        }
+    }
+    
+    /* reverse facet normals */
+    for (i = 1; i <= model->numfacetnorms; i++) {
+        model->facetnorms[3 * i + 0] = -model->facetnorms[3 * i + 0];
+        model->facetnorms[3 * i + 1] = -model->facetnorms[3 * i + 1];
+        model->facetnorms[3 * i + 2] = -model->facetnorms[3 * i + 2];
+    }
+    
+    /* reverse vertex normals */
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = -model->normals[3 * i + 0];
+        model->normals[3 * i + 1] = -model->normals[3 * i + 1];
+        model->normals[3 * i + 2] = -model->normals[3 * i + 2];
+    }
+}
+
+/* glmFacetNormals: Generates facet normals for a model (by taking the
+ * cross product of the two vectors derived from the sides of each
+ * triangle).  Assumes a counter-clockwise winding.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmFacetNormals(GLMmodel* model)
+{
+    GLuint  i;
+    GLfloat u[3];
+    GLfloat v[3];
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* clobber any old facetnormals */
+    if (model->facetnorms)
+        free(model->facetnorms);
+    
+    /* allocate memory for the new facet normals */
+    model->numfacetnorms = model->numtriangles;
+    model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) *
+                       3 * (model->numfacetnorms + 1));
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        model->triangles[i].findex = i+1;
+        
+        u[0] = model->vertices[3 * T(i).vindices[1] + 0] -
+            model->vertices[3 * T(i).vindices[0] + 0];
+        u[1] = model->vertices[3 * T(i).vindices[1] + 1] -
+            model->vertices[3 * T(i).vindices[0] + 1];
+        u[2] = model->vertices[3 * T(i).vindices[1] + 2] -
+            model->vertices[3 * T(i).vindices[0] + 2];
+        
+        v[0] = model->vertices[3 * T(i).vindices[2] + 0] -
+            model->vertices[3 * T(i).vindices[0] + 0];
+        v[1] = model->vertices[3 * T(i).vindices[2] + 1] -
+            model->vertices[3 * T(i).vindices[0] + 1];
+        v[2] = model->vertices[3 * T(i).vindices[2] + 2] -
+            model->vertices[3 * T(i).vindices[0] + 2];
+        
+        glmCross(u, v, &model->facetnorms[3 * (i+1)]);
+        glmNormalize(&model->facetnorms[3 * (i+1)]);
+    }
+}
+
+/* glmVertexNormals: Generates smooth vertex normals for a model.
+ * First builds a list of all the triangles each vertex is in.   Then
+ * loops through each vertex in the the list averaging all the facet
+ * normals of the triangles each vertex is in.   Finally, sets the
+ * normal index in the triangle for the vertex to the generated smooth
+ * normal.   If the dot product of a facet normal and the facet normal
+ * associated with the first triangle in the list of triangles the
+ * current vertex is in is greater than the cosine of the angle
+ * parameter to the function, that facet normal is not added into the
+ * average normal calculation and the corresponding vertex is given
+ * the facet normal.  This tends to preserve hard edges.  The angle to
+ * use depends on the model, but 90 degrees is usually a good start.
+ *
+ * model - initialized GLMmodel structure
+ * angle - maximum angle (in degrees) to smooth across
+ */
+GLvoid
+glmVertexNormals(GLMmodel* model, GLfloat angle)
+{
+    GLMnode*    node;
+    GLMnode*    tail;
+    GLMnode** members;
+    GLfloat*    normals;
+    GLuint  numnormals;
+    GLfloat average[3];
+    GLfloat dot, cos_angle;
+    GLuint  i, avg;
+    
+    assert(model);
+    assert(model->facetnorms);
+    
+    /* calculate the cosine of the angle (in degrees) */
+    cos_angle = cos(angle * M_PI / 180.0);
+    
+    /* nuke any previous normals */
+    if (model->normals)
+        free(model->normals);
+    
+    /* allocate space for new normals */
+    model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
+    
+    /* allocate a structure that will hold a linked list of triangle
+    indices for each vertex */
+    members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1));
+    for (i = 1; i <= model->numvertices; i++)
+        members[i] = NULL;
+    
+    /* for every triangle, create a node for each vertex in it */
+    for (i = 0; i < model->numtriangles; i++) {
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[0]];
+        members[T(i).vindices[0]] = node;
+        
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[1]];
+        members[T(i).vindices[1]] = node;
+        
+        node = (GLMnode*)malloc(sizeof(GLMnode));
+        node->index = i;
+        node->next  = members[T(i).vindices[2]];
+        members[T(i).vindices[2]] = node;
+    }
+    
+    /* calculate the average normal for each vertex */
+    numnormals = 1;
+    for (i = 1; i <= model->numvertices; i++) {
+    /* calculate an average normal for this vertex by averaging the
+        facet normal of every triangle this vertex is in */
+        node = members[i];
+        if (!node)
+            fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n");
+        average[0] = 0.0; average[1] = 0.0; average[2] = 0.0;
+        avg = 0;
+        while (node) {
+        /* only average if the dot product of the angle between the two
+        facet normals is greater than the cosine of the threshold
+        angle -- or, said another way, the angle between the two
+            facet normals is less than (or equal to) the threshold angle */
+            dot = glmDot(&model->facetnorms[3 * T(node->index).findex],
+                &model->facetnorms[3 * T(members[i]->index).findex]);
+            if (dot > cos_angle) {
+                node->averaged = GL_TRUE;
+                average[0] += model->facetnorms[3 * T(node->index).findex + 0];
+                average[1] += model->facetnorms[3 * T(node->index).findex + 1];
+                average[2] += model->facetnorms[3 * T(node->index).findex + 2];
+                avg = 1;            /* we averaged at least one normal! */
+            } else {
+                node->averaged = GL_FALSE;
+            }
+            node = node->next;
+        }
+        
+        if (avg) {
+            /* normalize the averaged normal */
+            glmNormalize(average);
+            
+            /* add the normal to the vertex normals list */
+            model->normals[3 * numnormals + 0] = average[0];
+            model->normals[3 * numnormals + 1] = average[1];
+            model->normals[3 * numnormals + 2] = average[2];
+            avg = numnormals;
+            numnormals++;
+        }
+        
+        /* set the normal of this vertex in each triangle it is in */
+        node = members[i];
+        while (node) {
+            if (node->averaged) {
+                /* if this node was averaged, use the average normal */
+                if (T(node->index).vindices[0] == i)
+                    T(node->index).nindices[0] = avg;
+                else if (T(node->index).vindices[1] == i)
+                    T(node->index).nindices[1] = avg;
+                else if (T(node->index).vindices[2] == i)
+                    T(node->index).nindices[2] = avg;
+            } else {
+                /* if this node wasn't averaged, use the facet normal */
+                model->normals[3 * numnormals + 0] = 
+                    model->facetnorms[3 * T(node->index).findex + 0];
+                model->normals[3 * numnormals + 1] = 
+                    model->facetnorms[3 * T(node->index).findex + 1];
+                model->normals[3 * numnormals + 2] = 
+                    model->facetnorms[3 * T(node->index).findex + 2];
+                if (T(node->index).vindices[0] == i)
+                    T(node->index).nindices[0] = numnormals;
+                else if (T(node->index).vindices[1] == i)
+                    T(node->index).nindices[1] = numnormals;
+                else if (T(node->index).vindices[2] == i)
+                    T(node->index).nindices[2] = numnormals;
+                numnormals++;
+            }
+            node = node->next;
+        }
+    }
+    
+    model->numnormals = numnormals - 1;
+    
+    /* free the member information */
+    for (i = 1; i <= model->numvertices; i++) {
+        node = members[i];
+        while (node) {
+            tail = node;
+            node = node->next;
+            free(tail);
+        }
+    }
+    free(members);
+    
+    /* pack the normals array (we previously allocated the maximum
+    number of normals that could possibly be created (numtriangles *
+    3), so get rid of some of them (usually alot unless none of the
+    facet normals were averaged)) */
+    normals = model->normals;
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = normals[3 * i + 0];
+        model->normals[3 * i + 1] = normals[3 * i + 1];
+        model->normals[3 * i + 2] = normals[3 * i + 2];
+    }
+    free(normals);
+}
+
+
+/* glmLinearTexture: Generates texture coordinates according to a
+ * linear projection of the texture map.  It generates these by
+ * linearly mapping the vertices onto a square.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmLinearTexture(GLMmodel* model)
+{
+    GLMgroup *group;
+    GLfloat dimensions[3];
+    GLfloat x, y, scalefactor;
+    GLuint i;
+    
+    assert(model);
+    
+    if (model->texcoords)
+        free(model->texcoords);
+    model->numtexcoords = model->numvertices;
+    model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
+    
+    glmDimensions(model, dimensions);
+    scalefactor = 2.0 / 
+        glmAbs(glmMax(glmMax(dimensions[0], dimensions[1]), dimensions[2]));
+    
+    /* do the calculations */
+    for(i = 1; i <= model->numvertices; i++) {
+        x = model->vertices[3 * i + 0] * scalefactor;
+        y = model->vertices[3 * i + 2] * scalefactor;
+        model->texcoords[2 * i + 0] = (x + 1.0) / 2.0;
+        model->texcoords[2 * i + 1] = (y + 1.0) / 2.0;
+    }
+    
+    /* go through and put texture coordinate indices in all the triangles */
+    group = model->groups;
+    while(group) {
+        for(i = 0; i < group->numtriangles; i++) {
+            T(group->triangles[i]).tindices[0] = T(group->triangles[i]).vindices[0];
+            T(group->triangles[i]).tindices[1] = T(group->triangles[i]).vindices[1];
+            T(group->triangles[i]).tindices[2] = T(group->triangles[i]).vindices[2];
+        }    
+        group = group->next;
+    }
+    
+#if 0
+    printf("glmLinearTexture(): generated %d linear texture coordinates\n",
+        model->numtexcoords);
+#endif
+}
+
+/* glmSpheremapTexture: Generates texture coordinates according to a
+ * spherical projection of the texture map.  Sometimes referred to as
+ * spheremap, or reflection map texture coordinates.  It generates
+ * these by using the normal to calculate where that vertex would map
+ * onto a sphere.  Since it is impossible to map something flat
+ * perfectly onto something spherical, there is distortion at the
+ * poles.  This particular implementation causes the poles along the X
+ * axis to be distorted.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmSpheremapTexture(GLMmodel* model)
+{
+    GLMgroup* group;
+    GLfloat theta, phi, rho, x, y, z, r;
+    GLuint i;
+    
+    assert(model);
+    assert(model->normals);
+    
+    if (model->texcoords)
+        free(model->texcoords);
+    model->numtexcoords = model->numnormals;
+    model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
+    
+    for (i = 1; i <= model->numnormals; i++) {
+        z = model->normals[3 * i + 0];  /* re-arrange for pole distortion */
+        y = model->normals[3 * i + 1];
+        x = model->normals[3 * i + 2];
+        r = sqrt((x * x) + (y * y));
+        rho = sqrt((r * r) + (z * z));
+        
+        if(r == 0.0) {
+            theta = 0.0;
+            phi = 0.0;
+        } else {
+            if(z == 0.0)
+                phi = 3.14159265f / 2.f;
+            else
+                phi = acos(z / rho);
+            
+            if(y == 0.0)
+                theta = 3.141592365f / 2.f;
+            else
+                theta = asin(y / r) + (3.14159265 / 2.0);
+        }
+        
+        model->texcoords[2 * i + 0] = theta / 3.14159265;
+        model->texcoords[2 * i + 1] = phi / 3.14159265;
+    }
+    
+    /* go through and put texcoord indices in all the triangles */
+    group = model->groups;
+    while(group) {
+        for (i = 0; i < group->numtriangles; i++) {
+            T(group->triangles[i]).tindices[0] = T(group->triangles[i]).nindices[0];
+            T(group->triangles[i]).tindices[1] = T(group->triangles[i]).nindices[1];
+            T(group->triangles[i]).tindices[2] = T(group->triangles[i]).nindices[2];
+        }
+        group = group->next;
+    }
+}
+
+/* glmDelete: Deletes a GLMmodel structure.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmDelete(GLMmodel* model)
+{
+    GLMgroup* group;
+    GLuint i;
+    
+    assert(model);
+    
+    if (model->pathname)     free(model->pathname);
+    if (model->mtllibname) free(model->mtllibname);
+    if (model->vertices)     free(model->vertices);
+    if (model->normals)  free(model->normals);
+    if (model->texcoords)  free(model->texcoords);
+    if (model->facetnorms) free(model->facetnorms);
+    if (model->triangles)  free(model->triangles);
+    if (model->materials) {
+        for (i = 0; i < model->nummaterials; i++)
+            free(model->materials[i].name);
+    }
+    free(model->materials);
+    while(model->groups) {
+        group = model->groups;
+        model->groups = model->groups->next;
+        free(group->name);
+        free(group->triangles);
+        free(group);
+    }
+    
+    free(model);
+}
+
+/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+ * Returns a pointer to the created object which should be free'd with
+ * glmDelete().
+ *
+ * filename - name of the file containing the Wavefront .OBJ format data.  
+ */
+GLMmodel* 
+glmReadOBJ(char* filename)
+{
+    GLMmodel* model;
+    FILE*   file;
+    
+    /* open the file */
+    file = fopen(filename, "r");
+    if (!file) {
+        fprintf(stderr, "glmReadOBJ() failed: can't open data file \"%s\".\n",
+            filename);
+        exit(1);
+    }
+    
+    /* allocate a new model */
+    model = (GLMmodel*)malloc(sizeof(GLMmodel));
+    model->pathname    = strdup(filename);
+    model->mtllibname    = NULL;
+    model->numvertices   = 0;
+    model->vertices    = NULL;
+    model->numnormals    = 0;
+    model->normals     = NULL;
+    model->numtexcoords  = 0;
+    model->texcoords       = NULL;
+    model->numfacetnorms = 0;
+    model->facetnorms    = NULL;
+    model->numtriangles  = 0;
+    model->triangles       = NULL;
+    model->nummaterials  = 0;
+    model->materials       = NULL;
+    model->numgroups       = 0;
+    model->groups      = NULL;
+    model->position[0]   = 0.0;
+    model->position[1]   = 0.0;
+    model->position[2]   = 0.0;
+    
+    /* make a first pass through the file to get a count of the number
+    of vertices, normals, texcoords & triangles */
+    glmFirstPass(model, file);
+    
+    /* allocate memory */
+    model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
+        3 * (model->numvertices + 1));
+    model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
+        model->numtriangles);
+    if (model->numnormals) {
+        model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
+            3 * (model->numnormals + 1));
+    }
+    if (model->numtexcoords) {
+        model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
+            2 * (model->numtexcoords + 1));
+    }
+    
+    /* rewind to beginning of file and read in the data this pass */
+    rewind(file);
+    
+    glmSecondPass(model, file);
+    
+    /* close the file */
+    fclose(file);
+    
+    return model;
+}
+
+/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+ * a file.
+ *
+ * model - initialized GLMmodel structure
+ * filename - name of the file to write the Wavefront .OBJ format data to
+ * mode  - a bitwise or of values describing what is written to the file
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *             GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLvoid
+glmWriteOBJ(GLMmodel* model, char* filename, GLuint mode)
+{
+    GLuint  i;
+    FILE*   file;
+    GLMgroup* group;
+    
+    assert(model);
+    
+    /* do a bit of warning */
+    if (mode & GLM_FLAT && !model->facetnorms) {
+        printf("glmWriteOBJ() warning: flat normal output requested "
+            "with no facet normals defined.\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_SMOOTH && !model->normals) {
+        printf("glmWriteOBJ() warning: smooth normal output requested "
+            "with no normals defined.\n");
+        mode &= ~GLM_SMOOTH;
+    }
+    if (mode & GLM_TEXTURE && !model->texcoords) {
+        printf("glmWriteOBJ() warning: texture coordinate output requested "
+            "with no texture coordinates defined.\n");
+        mode &= ~GLM_TEXTURE;
+    }
+    if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+        printf("glmWriteOBJ() warning: flat normal output requested "
+            "and smooth normal output requested (using smooth).\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_COLOR && !model->materials) {
+        printf("glmWriteOBJ() warning: color output requested "
+            "with no colors (materials) defined.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_MATERIAL && !model->materials) {
+        printf("glmWriteOBJ() warning: material output requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_MATERIAL;
+    }
+    if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
+        printf("glmWriteOBJ() warning: color and material output requested "
+            "outputting only materials.\n");
+        mode &= ~GLM_COLOR;
+    }
+    
+    
+    /* open the file */
+    file = fopen(filename, "w");
+    if (!file) {
+        fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n",
+            filename);
+        exit(1);
+    }
+    
+    /* spit out a header */
+    fprintf(file, "#  \n");
+    fprintf(file, "#  Wavefront OBJ generated by GLM library\n");
+    fprintf(file, "#  \n");
+    fprintf(file, "#  GLM library\n");
+    fprintf(file, "#  Nate Robins\n");
+    fprintf(file, "#  ndr@pobox.com\n");
+    fprintf(file, "#  http://www.pobox.com/~ndr\n");
+    fprintf(file, "#  \n");
+    
+    if (mode & GLM_MATERIAL && model->mtllibname) {
+        fprintf(file, "\nmtllib %s\n\n", model->mtllibname);
+        glmWriteMTL(model, filename, model->mtllibname);
+    }
+    
+    /* spit out the vertices */
+    fprintf(file, "\n");
+    fprintf(file, "# %d vertices\n", model->numvertices);
+    for (i = 1; i <= model->numvertices; i++) {
+        fprintf(file, "v %f %f %f\n", 
+            model->vertices[3 * i + 0],
+            model->vertices[3 * i + 1],
+            model->vertices[3 * i + 2]);
+    }
+    
+    /* spit out the smooth/flat normals */
+    if (mode & GLM_SMOOTH) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d normals\n", model->numnormals);
+        for (i = 1; i <= model->numnormals; i++) {
+            fprintf(file, "vn %f %f %f\n", 
+                model->normals[3 * i + 0],
+                model->normals[3 * i + 1],
+                model->normals[3 * i + 2]);
+        }
+    } else if (mode & GLM_FLAT) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d normals\n", model->numfacetnorms);
+        for (i = 1; i <= model->numnormals; i++) {
+            fprintf(file, "vn %f %f %f\n", 
+                model->facetnorms[3 * i + 0],
+                model->facetnorms[3 * i + 1],
+                model->facetnorms[3 * i + 2]);
+        }
+    }
+    
+    /* spit out the texture coordinates */
+    if (mode & GLM_TEXTURE) {
+        fprintf(file, "\n");
+        fprintf(file, "# %d texcoords\n", (int)(model->texcoords));
+        for (i = 1; i <= model->numtexcoords; i++) {
+            fprintf(file, "vt %f %f\n", 
+                model->texcoords[2 * i + 0],
+                model->texcoords[2 * i + 1]);
+        }
+    }
+    
+    fprintf(file, "\n");
+    fprintf(file, "# %d groups\n", model->numgroups);
+    fprintf(file, "# %d faces (triangles)\n", model->numtriangles);
+    fprintf(file, "\n");
+    
+    group = model->groups;
+    while(group) {
+        fprintf(file, "g %s\n", group->name);
+        if (mode & GLM_MATERIAL)
+            fprintf(file, "usemtl %s\n", model->materials[group->material].name);
+        for (i = 0; i < group->numtriangles; i++) {
+            if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
+                    T(group->triangles[i]).vindices[0], 
+                    T(group->triangles[i]).nindices[0], 
+                    T(group->triangles[i]).tindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).nindices[1],
+                    T(group->triangles[i]).tindices[1],
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).nindices[2],
+                    T(group->triangles[i]).tindices[2]);
+            } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d %d/%d %d/%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).findex);
+            } else if (mode & GLM_TEXTURE) {
+                fprintf(file, "f %d/%d %d/%d %d/%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).tindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).tindices[1],
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).tindices[2]);
+            } else if (mode & GLM_SMOOTH) {
+                fprintf(file, "f %d//%d %d//%d %d//%d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).nindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).nindices[1],
+                    T(group->triangles[i]).vindices[2], 
+                    T(group->triangles[i]).nindices[2]);
+            } else if (mode & GLM_FLAT) {
+                fprintf(file, "f %d//%d %d//%d %d//%d\n",
+                    T(group->triangles[i]).vindices[0], 
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).findex,
+                    T(group->triangles[i]).vindices[2],
+                    T(group->triangles[i]).findex);
+            } else {
+                fprintf(file, "f %d %d %d\n",
+                    T(group->triangles[i]).vindices[0],
+                    T(group->triangles[i]).vindices[1],
+                    T(group->triangles[i]).vindices[2]);
+            }
+        }
+        fprintf(file, "\n");
+        group = group->next;
+    }
+    
+    fclose(file);
+}
+
+/* glmDraw: Renders the model to the current OpenGL context using the
+ * mode specified.
+ *
+ * model - initialized GLMmodel structure
+ * mode  - a bitwise OR of values describing what is to be rendered.
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ *             GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLvoid
+glmDraw(GLMmodel* model, GLuint mode)
+{
+    static GLuint i;
+    static GLMgroup* group;
+    static GLMtriangle* triangle;
+    static GLMmaterial* material;
+    
+    assert(model);
+    assert(model->vertices);
+    
+    /* do a bit of warning */
+    if (mode & GLM_FLAT && !model->facetnorms) {
+        printf("glmDraw() warning: flat render mode requested "
+            "with no facet normals defined.\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_SMOOTH && !model->normals) {
+        printf("glmDraw() warning: smooth render mode requested "
+            "with no normals defined.\n");
+        mode &= ~GLM_SMOOTH;
+    }
+    if (mode & GLM_TEXTURE && !model->texcoords) {
+        printf("glmDraw() warning: texture render mode requested "
+            "with no texture coordinates defined.\n");
+        mode &= ~GLM_TEXTURE;
+    }
+    if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
+        printf("glmDraw() warning: flat render mode requested "
+            "and smooth render mode requested (using smooth).\n");
+        mode &= ~GLM_FLAT;
+    }
+    if (mode & GLM_COLOR && !model->materials) {
+        printf("glmDraw() warning: color render mode requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_MATERIAL && !model->materials) {
+        printf("glmDraw() warning: material render mode requested "
+            "with no materials defined.\n");
+        mode &= ~GLM_MATERIAL;
+    }
+    if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
+        printf("glmDraw() warning: color and material render mode requested "
+            "using only material mode.\n");
+        mode &= ~GLM_COLOR;
+    }
+    if (mode & GLM_COLOR)
+        glEnable(GL_COLOR_MATERIAL);
+    else if (mode & GLM_MATERIAL)
+        glDisable(GL_COLOR_MATERIAL);
+    
+    /* perhaps this loop should be unrolled into material, color, flat,
+       smooth, etc. loops?  since most cpu's have good branch prediction
+       schemes (and these branches will always go one way), probably
+       wouldn't gain too much?  */
+    
+    group = model->groups;
+    while (group) {
+        if (mode & GLM_MATERIAL) {
+            material = &model->materials[group->material];
+            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient);
+            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse);
+            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material->specular);
+            glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess);
+        }
+        
+        if (mode & GLM_COLOR) {
+            glColor3fv(material->diffuse);
+        }
+        
+        glBegin(GL_TRIANGLES);
+        for (i = 0; i < group->numtriangles; i++) {
+            triangle = &T(group->triangles[i]);
+            
+            if (mode & GLM_FLAT)
+                glNormal3fv(&model->facetnorms[3 * triangle->findex]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[0]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[0]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[0]]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[1]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[1]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[1]]);
+            
+            if (mode & GLM_SMOOTH)
+                glNormal3fv(&model->normals[3 * triangle->nindices[2]]);
+            if (mode & GLM_TEXTURE)
+                glTexCoord2fv(&model->texcoords[2 * triangle->tindices[2]]);
+            glVertex3fv(&model->vertices[3 * triangle->vindices[2]]);
+            
+        }
+        glEnd();
+        
+        group = group->next;
+    }
+}
+
+/* glmList: Generates and returns a display list for the model using
+ * the mode specified.
+ *
+ * model - initialized GLMmodel structure
+ * mode  - a bitwise OR of values describing what is to be rendered.
+ *             GLM_NONE     -  render with only vertices
+ *             GLM_FLAT     -  render with facet normals
+ *             GLM_SMOOTH   -  render with vertex normals
+ *             GLM_TEXTURE  -  render with texture coords
+ *             GLM_COLOR    -  render with colors (color material)
+ *             GLM_MATERIAL -  render with materials
+ *             GLM_COLOR and GLM_MATERIAL should not both be specified.  
+ * GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLuint
+glmList(GLMmodel* model, GLuint mode)
+{
+    GLuint list;
+    
+    list = glGenLists(1);
+    glNewList(list, GL_COMPILE);
+    glmDraw(model, mode);
+    glEndList();
+    
+    return list;
+}
+
+/* glmWeld: eliminate (weld) vectors that are within an epsilon of
+ * each other.
+ *
+ * model   - initialized GLMmodel structure
+ * epsilon     - maximum difference between vertices
+ *               ( 0.00001 is a good start for a unitized model)
+ *
+ */
+GLvoid
+glmWeld(GLMmodel* model, GLfloat epsilon)
+{
+    GLfloat* vectors;
+    GLfloat* copies;
+    GLuint   numvectors;
+    GLuint   i;
+    
+    /* vertices */
+    numvectors = model->numvertices;
+    vectors  = model->vertices;
+    copies = glmWeldVectors(vectors, &numvectors, epsilon);
+    
+#if 1
+    printf("glmWeld(): %d redundant vertices.\n", 
+        model->numvertices - numvectors - 1);
+#endif
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        T(i).vindices[0] = (GLuint)vectors[3 * T(i).vindices[0] + 0];
+        T(i).vindices[1] = (GLuint)vectors[3 * T(i).vindices[1] + 0];
+        T(i).vindices[2] = (GLuint)vectors[3 * T(i).vindices[2] + 0];
+    }
+    
+    /* free space for old vertices */
+    free(vectors);
+    
+    /* allocate space for the new vertices */
+    model->numvertices = numvectors;
+    model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * 
+        3 * (model->numvertices + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numvertices; i++) {
+        model->vertices[3 * i + 0] = copies[3 * i + 0];
+        model->vertices[3 * i + 1] = copies[3 * i + 1];
+        model->vertices[3 * i + 2] = copies[3 * i + 2];
+    }
+    
+    free(copies);
+}
+
+/* glmReadPPM: read a PPM raw (type P6) file.  The PPM file has a header
+ * that should look something like:
+ *
+ *    P6
+ *    # comment
+ *    width height max_value
+ *    rgbrgbrgb...
+ *
+ * where "P6" is the magic cookie which identifies the file type and
+ * should be the only characters on the first line followed by a
+ * carriage return.  Any line starting with a # mark will be treated
+ * as a comment and discarded.   After the magic cookie, three integer
+ * values are expected: width, height of the image and the maximum
+ * value for a pixel (max_value must be < 256 for PPM raw files).  The
+ * data section consists of width*height rgb triplets (one byte each)
+ * in binary format (i.e., such as that written with fwrite() or
+ * equivalent).
+ *
+ * The rgb data is returned as an array of unsigned chars (packed
+ * rgb).  The malloc()'d memory should be free()'d by the caller.  If
+ * an error occurs, an error message is sent to stderr and NULL is
+ * returned.
+ *
+ * filename   - name of the .ppm file.
+ * width      - will contain the width of the image on return.
+ * height     - will contain the height of the image on return.
+ *
+ */
+GLubyte* 
+glmReadPPM(char* filename, int* width, int* height)
+{
+    FILE* fp;
+    int i, w, h, d;
+    unsigned char* image;
+    char head[70];          /* max line <= 70 in PPM (per spec). */
+    
+    fp = fopen(filename, "rb");
+    if (!fp) {
+        perror(filename);
+        return NULL;
+    }
+    
+    /* grab first two chars of the file and make sure that it has the
+       correct magic cookie for a raw PPM file. */
+    fgets(head, 70, fp);
+    if (strncmp(head, "P6", 2)) {
+        fprintf(stderr, "%s: Not a raw PPM file\n", filename);
+        return NULL;
+    }
+    
+    /* grab the three elements in the header (height, width, maxval). */
+    i = 0;
+    while(i < 3) {
+        fgets(head, 70, fp);
+        if (head[0] == '#')     /* skip comments. */
+            continue;
+        if (i == 0)
+            i += sscanf(head, "%d %d %d", &h, &w, &d);
+        else if (i == 1)
+            i += sscanf(head, "%d %d", &w, &d);
+        else if (i == 2)
+            i += sscanf(head, "%d", &d);
+    }
+    
+    /* grab all the image data in one fell swoop. */
+    image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
+    fread(image, sizeof(unsigned char), w*h*3, fp);
+    fclose(fp);
+    
+    *width = w;
+    *height = h;
+    return image;
+}
+
+#if 0
+/* normals */
+if (model->numnormals) {
+    numvectors = model->numnormals;
+    vectors  = model->normals;
+    copies = glmOptimizeVectors(vectors, &numvectors);
+    
+    printf("glmOptimize(): %d redundant normals.\n", 
+        model->numnormals - numvectors);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        T(i).nindices[0] = (GLuint)vectors[3 * T(i).nindices[0] + 0];
+        T(i).nindices[1] = (GLuint)vectors[3 * T(i).nindices[1] + 0];
+        T(i).nindices[2] = (GLuint)vectors[3 * T(i).nindices[2] + 0];
+    }
+    
+    /* free space for old normals */
+    free(vectors);
+    
+    /* allocate space for the new normals */
+    model->numnormals = numvectors;
+    model->normals = (GLfloat*)malloc(sizeof(GLfloat) * 
+        3 * (model->numnormals + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numnormals; i++) {
+        model->normals[3 * i + 0] = copies[3 * i + 0];
+        model->normals[3 * i + 1] = copies[3 * i + 1];
+        model->normals[3 * i + 2] = copies[3 * i + 2];
+    }
+    
+    free(copies);
+}
+
+/* texcoords */
+if (model->numtexcoords) {
+    numvectors = model->numtexcoords;
+    vectors  = model->texcoords;
+    copies = glmOptimizeVectors(vectors, &numvectors);
+    
+    printf("glmOptimize(): %d redundant texcoords.\n", 
+        model->numtexcoords - numvectors);
+    
+    for (i = 0; i < model->numtriangles; i++) {
+        for (j = 0; j < 3; j++) {
+            T(i).tindices[j] = (GLuint)vectors[3 * T(i).tindices[j] + 0];
+        }
+    }
+    
+    /* free space for old texcoords */
+    free(vectors);
+    
+    /* allocate space for the new texcoords */
+    model->numtexcoords = numvectors;
+    model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 
+        2 * (model->numtexcoords + 1));
+    
+    /* copy the optimized vertices into the actual vertex list */
+    for (i = 1; i <= model->numtexcoords; i++) {
+        model->texcoords[2 * i + 0] = copies[2 * i + 0];
+        model->texcoords[2 * i + 1] = copies[2 * i + 1];
+    }
+    
+    free(copies);
+}
+#endif
+
+#if 0
+/* look for unused vertices */
+/* look for unused normals */
+/* look for unused texcoords */
+for (i = 1; i <= model->numvertices; i++) {
+    for (j = 0; j < model->numtriangles; i++) {
+        if (T(j).vindices[0] == i || 
+            T(j).vindices[1] == i || 
+            T(j).vindices[1] == i)
+            break;
+    }
+}
+#endif
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/glm.h	(revision 4)
@@ -0,0 +1,291 @@
+/*    
+      glm.h
+      Nate Robins, 1997, 2000
+      nate@pobox.com, http://www.pobox.com/~nate
+ 
+      Wavefront OBJ model file format reader/writer/manipulator.
+
+      Includes routines for generating smooth normals with
+      preservation of edges, welding redundant vertices & texture
+      coordinate generation (spheremap and planar projections) + more.
+
+ */
+#ifndef __GLM_H__
+#define __GLM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+#ifndef M_PI
+#define M_PI 3.14159265f
+#endif
+
+#define GLM_NONE     (0)            /* render with only vertices */
+#define GLM_FLAT     (1 << 0)       /* render with facet normals */
+#define GLM_SMOOTH   (1 << 1)       /* render with vertex normals */
+#define GLM_TEXTURE  (1 << 2)       /* render with texture coords */
+#define GLM_COLOR    (1 << 3)       /* render with colors */
+#define GLM_MATERIAL (1 << 4)       /* render with materials */
+
+
+/* GLMmaterial: Structure that defines a material in a model. 
+ */
+typedef struct _GLMmaterial
+{
+  char* name;                   /* name of material */
+  GLfloat diffuse[4];           /* diffuse component */
+  GLfloat ambient[4];           /* ambient component */
+  GLfloat specular[4];          /* specular component */
+  GLfloat emmissive[4];         /* emmissive component */
+  GLfloat shininess;            /* specular exponent */
+} GLMmaterial;
+
+/* GLMtriangle: Structure that defines a triangle in a model.
+ */
+typedef struct _GLMtriangle {
+  GLuint vindices[3];           /* array of triangle vertex indices */
+  GLuint nindices[3];           /* array of triangle normal indices */
+  GLuint tindices[3];           /* array of triangle texcoord indices*/
+  GLuint findex;                /* index of triangle facet normal */
+} GLMtriangle;
+
+/* GLMgroup: Structure that defines a group in a model.
+ */
+typedef struct _GLMgroup {
+  char*             name;           /* name of this group */
+  GLuint            numtriangles;   /* number of triangles in this group */
+  GLuint*           triangles;      /* array of triangle indices */
+  GLuint            material;       /* index to material for group */
+  struct _GLMgroup* next;           /* pointer to next group in model */
+} GLMgroup;
+
+/* GLMmodel: Structure that defines a model.
+ */
+typedef struct _GLMmodel {
+  char*    pathname;            /* path to this model */
+  char*    mtllibname;          /* name of the material library */
+
+  GLuint   numvertices;         /* number of vertices in model */
+  GLfloat* vertices;            /* array of vertices  */
+
+  GLuint   numnormals;          /* number of normals in model */
+  GLfloat* normals;             /* array of normals */
+
+  GLuint   numtexcoords;        /* number of texcoords in model */
+  GLfloat* texcoords;           /* array of texture coordinates */
+
+  GLuint   numfacetnorms;       /* number of facetnorms in model */
+  GLfloat* facetnorms;          /* array of facetnorms */
+
+  GLuint       numtriangles;    /* number of triangles in model */
+  GLMtriangle* triangles;       /* array of triangles */
+
+  GLuint       nummaterials;    /* number of materials in model */
+  GLMmaterial* materials;       /* array of materials */
+
+  GLuint       numgroups;       /* number of groups in model */
+  GLMgroup*    groups;          /* linked list of groups */
+
+  GLfloat position[3];          /* position of the model */
+
+} GLMmodel;
+
+
+/* glmUnitize: "unitize" a model by translating it to the origin and
+ * scaling it to fit in a unit cube around the origin.  Returns the
+ * scalefactor used.
+ *
+ * model - properly initialized GLMmodel structure 
+ */
+GLfloat
+glmUnitize(GLMmodel* model);
+
+/* glmDimensions: Calculates the dimensions (width, height, depth) of
+ * a model.
+ *
+ * model      - initialized GLMmodel structure
+ * dimensions - array of 3 GLfloats (GLfloat dimensions[3])
+ */
+GLvoid
+glmDimensions(GLMmodel* model, GLfloat* dimensions);
+
+/* glmScale: Scales a model by a given amount.
+ * 
+ * model - properly initialized GLMmodel structure
+ * scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
+ */
+GLvoid
+glmScale(GLMmodel* model, GLfloat scale);
+
+/* glmReverseWinding: Reverse the polygon winding for all polygons in
+ * this model.  Default winding is counter-clockwise.  Also changes
+ * the direction of the normals.
+ * 
+ * model - properly initialized GLMmodel structure 
+ */
+GLvoid
+glmReverseWinding(GLMmodel* model);
+
+/* glmFacetNormals: Generates facet normals for a model (by taking the
+ * cross product of the two vectors derived from the sides of each
+ * triangle).  Assumes a counter-clockwise winding.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmFacetNormals(GLMmodel* model);
+
+/* glmVertexNormals: Generates smooth vertex normals for a model.
+ * First builds a list of all the triangles each vertex is in.  Then
+ * loops through each vertex in the the list averaging all the facet
+ * normals of the triangles each vertex is in.  Finally, sets the
+ * normal index in the triangle for the vertex to the generated smooth
+ * normal.  If the dot product of a facet normal and the facet normal
+ * associated with the first triangle in the list of triangles the
+ * current vertex is in is greater than the cosine of the angle
+ * parameter to the function, that facet normal is not added into the
+ * average normal calculation and the corresponding vertex is given
+ * the facet normal.  This tends to preserve hard edges.  The angle to
+ * use depends on the model, but 90 degrees is usually a good start.
+ *
+ * model - initialized GLMmodel structure
+ * angle - maximum angle (in degrees) to smooth across
+ */
+GLvoid
+glmVertexNormals(GLMmodel* model, GLfloat angle);
+
+/* glmLinearTexture: Generates texture coordinates according to a
+ * linear projection of the texture map.  It generates these by
+ * linearly mapping the vertices onto a square.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmLinearTexture(GLMmodel* model);
+
+/* glmSpheremapTexture: Generates texture coordinates according to a
+ * spherical projection of the texture map.  Sometimes referred to as
+ * spheremap, or reflection map texture coordinates.  It generates
+ * these by using the normal to calculate where that vertex would map
+ * onto a sphere.  Since it is impossible to map something flat
+ * perfectly onto something spherical, there is distortion at the
+ * poles.  This particular implementation causes the poles along the X
+ * axis to be distorted.
+ *
+ * model - pointer to initialized GLMmodel structure
+ */
+GLvoid
+glmSpheremapTexture(GLMmodel* model);
+
+/* glmDelete: Deletes a GLMmodel structure.
+ *
+ * model - initialized GLMmodel structure
+ */
+GLvoid
+glmDelete(GLMmodel* model);
+
+/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
+ * Returns a pointer to the created object which should be free'd with
+ * glmDelete().
+ *
+ * filename - name of the file containing the Wavefront .OBJ format data.  
+ */
+GLMmodel* 
+glmReadOBJ(char* filename);
+
+/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
+ * a file.
+ *
+ * model    - initialized GLMmodel structure
+ * filename - name of the file to write the Wavefront .OBJ format data to
+ * mode     - a bitwise or of values describing what is written to the file
+ *            GLM_NONE    -  write only vertices
+ *            GLM_FLAT    -  write facet normals
+ *            GLM_SMOOTH  -  write vertex normals
+ *            GLM_TEXTURE -  write texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.
+ */
+GLvoid
+glmWriteOBJ(GLMmodel* model, char* filename, GLuint mode);
+
+/* glmDraw: Renders the model to the current OpenGL context using the
+ * mode specified.
+ *
+ * model    - initialized GLMmodel structure
+ * mode     - a bitwise OR of values describing what is to be rendered.
+ *            GLM_NONE    -  render with only vertices
+ *            GLM_FLAT    -  render with facet normals
+ *            GLM_SMOOTH  -  render with vertex normals
+ *            GLM_TEXTURE -  render with texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.
+ */
+GLvoid
+glmDraw(GLMmodel* model, GLuint mode);
+
+/* glmList: Generates and returns a display list for the model using
+ * the mode specified.
+ *
+ * model    - initialized GLMmodel structure
+ * mode     - a bitwise OR of values describing what is to be rendered.
+ *            GLM_NONE    -  render with only vertices
+ *            GLM_FLAT    -  render with facet normals
+ *            GLM_SMOOTH  -  render with vertex normals
+ *            GLM_TEXTURE -  render with texture coords
+ *            GLM_FLAT and GLM_SMOOTH should not both be specified.  
+ */
+GLuint
+glmList(GLMmodel* model, GLuint mode);
+
+/* glmWeld: eliminate (weld) vectors that are within an epsilon of
+ * each other.
+ *
+ * model      - initialized GLMmodel structure
+ * epsilon    - maximum difference between vertices
+ *              ( 0.00001 is a good start for a unitized model)
+ *
+ */
+GLvoid
+glmWeld(GLMmodel* model, GLfloat epsilon);
+
+/* glmReadPPM: read a PPM raw (type P6) file.  The PPM file has a header
+ * that should look something like:
+ *
+ *    P6
+ *    # comment
+ *    width height max_value
+ *    rgbrgbrgb...
+ *
+ * where "P6" is the magic cookie which identifies the file type and
+ * should be the only characters on the first line followed by a
+ * carriage return.  Any line starting with a # mark will be treated
+ * as a comment and discarded.   After the magic cookie, three integer
+ * values are expected: width, height of the image and the maximum
+ * value for a pixel (max_value must be < 256 for PPM raw files).  The
+ * data section consists of width*height rgb triplets (one byte each)
+ * in binary format (i.e., such as that written with fwrite() or
+ * equivalent).
+ *
+ * The rgb data is returned as an array of unsigned chars (packed
+ * rgb).  The malloc()'d memory should be free()'d by the caller.  If
+ * an error occurs, an error message is sent to stderr and NULL is
+ * returned.
+ *
+ * filename   - name of the .ppm file.
+ * width      - will contain the width of the image on return.
+ * height     - will contain the height of the image on return.
+ *
+ */
+GLubyte* 
+glmReadPPM(char* filename, int* width, int* height);
+
+// XBL200611111410 - Close the 'extern "C"' and the __GLM_H__ define.
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // __GLM_H__
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/projdesigner_default.vcproj
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/projdesigner_default.vcproj	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/projdesigner_default.vcproj	(revision 4)
@@ -0,0 +1,730 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="projdesigner_default"
+	ProjectGUID="{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}"
+	Keyword="Qt4VSv1.0"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="."
+			IntermediateDirectory="debug\"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -w34100 -w34189 -Zm200 -w34100 -w34189 -w34100 -w34189"
+				Optimization="4"
+				AdditionalIncludeDirectories="&quot;$(QTDIR)\include\QtCore&quot;,&quot;$(QTDIR)\include\QtGui&quot;,&quot;$(QTDIR)\include\QtOpenGL&quot;,&quot;$(QTDIR)\include\QtXml&quot;,&quot;$(QTDIR)\include&quot;,&quot;..\..&quot;,&quot;$(QTDIR)\include\ActiveQt&quot;,&quot;debug&quot;,&quot;.&quot;,&quot;.&quot;,$(QTDIR)\mkspecs\win32-msvc2005"
+				PreprocessorDefinitions="UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_STATICPLUGIN,QT_PLUGIN,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="false"
+				TreatWChar_tAsBuiltInType="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="debug\"
+				ObjectFile="debug\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_STATICPLUGIN,QT_PLUGIN,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT,_DEBUG"
+				ResourceOutputFileName="/$(InputName).res"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile=".\projdesigner_default.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="."
+			IntermediateDirectory="release\"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				WarningLevel="0"
+				DefaultCharType="0"
+				EnableErrorChecks="1"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="-Zm200 -w34100 -w34189 -Zm200 -w34100 -w34189 -w34100 -w34189"
+				Optimization="2"
+				WholeProgramOptimization="true"
+				AdditionalIncludeDirectories="&quot;$(QTDIR)\include\QtCore&quot;,&quot;$(QTDIR)\include\QtGui&quot;,&quot;$(QTDIR)\include\QtOpenGL&quot;,&quot;$(QTDIR)\include\QtXml&quot;,&quot;$(QTDIR)\include&quot;,&quot;..\..&quot;,&quot;$(QTDIR)\include\ActiveQt&quot;,&quot;release&quot;,&quot;.&quot;,&quot;.&quot;,$(QTDIR)\mkspecs\win32-msvc2005"
+				PreprocessorDefinitions="QT_NO_DEBUG,NDEBUG,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_NO_DEBUG,QT_STATICPLUGIN,QT_PLUGIN,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT,NDEBUG"
+				GeneratePreprocessedFile="0"
+				ExceptionHandling="1"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				TreatWChar_tAsBuiltInType="false"
+				RuntimeTypeInfo="true"
+				AssemblerListingLocation="release\"
+				ObjectFile="release\"
+				ProgramDataBaseFileName=".\"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="QT_NO_DEBUG,NDEBUG,UNICODE,WIN32,QT_LARGEFILE_SUPPORT,QT_NO_DEBUG,QT_STATICPLUGIN,QT_PLUGIN,QT_XML_LIB,QT_OPENGL_LIB,QT_GUI_LIB,QT_CORE_LIB,QT_THREAD_SUPPORT"
+				ResourceOutputFileName="/$(InputName).res"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile=".\projdesigner_default.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="DefaultCubemapSceneContent.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultCubemapSceneWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneContent.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneContent.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="defaultplugin.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultProjectorData.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultProjectorWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneContent.cpp"
+				>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneWidget.cpp"
+				>
+			</File>
+			<File
+				RelativePath="glm.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="DefaultCubemapSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultCubemapSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultCubemapSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultCubemapSceneWidget.h -o debug\moc_DefaultCubemapSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultCubemapSceneWidget.h"
+						Outputs="debug\moc_DefaultCubemapSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultCubemapSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultCubemapSceneWidget.h -o release\moc_DefaultCubemapSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultCubemapSceneWidget.h"
+						Outputs="release\moc_DefaultCubemapSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultEmptySceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultEmptySceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultEmptySceneWidget.h -o debug\moc_DefaultEmptySceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultEmptySceneWidget.h"
+						Outputs="debug\moc_DefaultEmptySceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultEmptySceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultEmptySceneWidget.h -o release\moc_DefaultEmptySceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultEmptySceneWidget.h"
+						Outputs="release\moc_DefaultEmptySceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultModelSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultModelSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultModelSceneWidget.h -o debug\moc_DefaultModelSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultModelSceneWidget.h"
+						Outputs="debug\moc_DefaultModelSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultModelSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultModelSceneWidget.h -o release\moc_DefaultModelSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultModelSceneWidget.h"
+						Outputs="release\moc_DefaultModelSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultplugin.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC defaultplugin.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 defaultplugin.h -o debug\moc_defaultplugin.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;defaultplugin.h"
+						Outputs="debug\moc_defaultplugin.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC defaultplugin.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 defaultplugin.h -o release\moc_defaultplugin.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;defaultplugin.h"
+						Outputs="release\moc_defaultplugin.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultProjectorData.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultProjectorWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultProjectorWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultProjectorWidget.h -o debug\moc_DefaultProjectorWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultProjectorWidget.h"
+						Outputs="debug\moc_DefaultProjectorWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultProjectorWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultProjectorWidget.h -o release\moc_DefaultProjectorWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultProjectorWidget.h"
+						Outputs="release\moc_DefaultProjectorWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneContent.h"
+				>
+			</File>
+			<File
+				RelativePath="DefaultTeapotSceneWidget.h"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultTeapotSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;debug&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultTeapotSceneWidget.h -o debug\moc_DefaultTeapotSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultTeapotSceneWidget.h"
+						Outputs="debug\moc_DefaultTeapotSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="MOC DefaultTeapotSceneWidget.h"
+						CommandLine="$(QTDIR)\bin\moc.exe  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_NO_DEBUG -DQT_STATICPLUGIN -DQT_PLUGIN -DQT_XML_LIB -DQT_OPENGL_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I&quot;$(QTDIR)\include\QtCore&quot; -I&quot;$(QTDIR)\include\QtGui&quot; -I&quot;$(QTDIR)\include\QtOpenGL&quot; -I&quot;$(QTDIR)\include\QtXml&quot; -I&quot;$(QTDIR)\include&quot; -I&quot;..\..&quot; -I&quot;$(QTDIR)\include\ActiveQt&quot; -I&quot;release&quot; -I&quot;.&quot; -I&quot;.&quot; -I$(QTDIR)\mkspecs\win32-msvc2005 -D_MSC_VER=1400 -DWIN32 DefaultTeapotSceneWidget.h -o release\moc_DefaultTeapotSceneWidget.cpp&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\moc.exe;DefaultTeapotSceneWidget.h"
+						Outputs="release\moc_DefaultTeapotSceneWidget.cpp"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="glm.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Generated Files"
+			Filter="cpp;c;cxx;moc;h;def;odl;idl;res;"
+			UniqueIdentifier="{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}"
+			>
+			<File
+				RelativePath="release\moc_DefaultCubemapSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultCubemapSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultEmptySceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultEmptySceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultModelSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultModelSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_defaultplugin.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_defaultplugin.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultProjectorWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultProjectorWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="release\moc_DefaultTeapotSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="debug\moc_DefaultTeapotSceneWidget.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="ui_defaultcubemapscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultemptyscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultmodelscenewidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultprojectorwidget.h"
+				>
+			</File>
+			<File
+				RelativePath="ui_defaultteapotscenewidget.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Form Files"
+			Filter="ui"
+			UniqueIdentifier="{99349809-55BA-4b9d-BF79-8FDBB0286EB3}"
+			ParseFiles="false"
+			>
+			<File
+				RelativePath="defaultcubemapscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultcubemapscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultcubemapscenewidget.ui -o ui_defaultcubemapscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultcubemapscenewidget.ui"
+						Outputs="ui_defaultcubemapscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultcubemapscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultcubemapscenewidget.ui -o ui_defaultcubemapscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultcubemapscenewidget.ui"
+						Outputs="ui_defaultcubemapscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultemptyscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultemptyscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultemptyscenewidget.ui -o ui_defaultemptyscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultemptyscenewidget.ui"
+						Outputs="ui_defaultemptyscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultemptyscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultemptyscenewidget.ui -o ui_defaultemptyscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultemptyscenewidget.ui"
+						Outputs="ui_defaultemptyscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultmodelscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultmodelscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultmodelscenewidget.ui -o ui_defaultmodelscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultmodelscenewidget.ui"
+						Outputs="ui_defaultmodelscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultmodelscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultmodelscenewidget.ui -o ui_defaultmodelscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultmodelscenewidget.ui"
+						Outputs="ui_defaultmodelscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultprojectorwidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultprojectorwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultprojectorwidget.ui -o ui_defaultprojectorwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultprojectorwidget.ui"
+						Outputs="ui_defaultprojectorwidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultprojectorwidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultprojectorwidget.ui -o ui_defaultprojectorwidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultprojectorwidget.ui"
+						Outputs="ui_defaultprojectorwidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="defaultteapotscenewidget.ui"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultteapotscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultteapotscenewidget.ui -o ui_defaultteapotscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultteapotscenewidget.ui"
+						Outputs="ui_defaultteapotscenewidget.h"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						Description="UIC defaultteapotscenewidget.ui"
+						CommandLine="$(QTDIR)\bin\uic.exe defaultteapotscenewidget.ui -o ui_defaultteapotscenewidget.h&#x0D;&#x0A;"
+						AdditionalDependencies="$(QTDIR)\bin\uic.exe;defaultteapotscenewidget.ui"
+						Outputs="ui_defaultteapotscenewidget.h"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+		<Global
+			Name="QtVersion"
+			Value="4.5.1"
+		/>
+	</Globals>
+</VisualStudioProject>
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultcubemapscenewidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultcubemapscenewidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultcubemapscenewidget.h	(revision 4)
@@ -0,0 +1,238 @@
+/********************************************************************************
+** Form generated from reading ui file 'defaultcubemapscenewidget.ui'
+**
+** Created: Mon 27. Apr 14:23:54 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DEFAULTCUBEMAPSCENEWIDGET_H
+#define UI_DEFAULTCUBEMAPSCENEWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_DefaultCubemapSceneWidget
+{
+public:
+    QGridLayout *gridLayout;
+    QGroupBox *projectionGroup;
+    QGridLayout *gridLayout1;
+    QGridLayout *gridLayout2;
+    QLineEdit *topFileNameEdit;
+    QLineEdit *frontFileNameEdit;
+    QPushButton *backBrowseButton;
+    QLineEdit *backFileNameEdit;
+    QLabel *bottomLabel;
+    QPushButton *frontBrowseButton;
+    QLabel *leftLabel;
+    QPushButton *topBrowseButton;
+    QLineEdit *bottomFileNameEdit;
+    QLabel *topLabel;
+    QPushButton *rightBrowseButton;
+    QPushButton *bottomBrowseButton;
+    QLabel *rightLabel;
+    QPushButton *leftBrowseButton;
+    QLabel *frontLabel;
+    QLineEdit *rightFileNameEdit;
+    QLineEdit *leftFileNameEdit;
+    QLabel *backLabel;
+    QSpacerItem *spacerItem;
+
+    void setupUi(QWidget *DefaultCubemapSceneWidget)
+    {
+        if (DefaultCubemapSceneWidget->objectName().isEmpty())
+            DefaultCubemapSceneWidget->setObjectName(QString::fromUtf8("DefaultCubemapSceneWidget"));
+        DefaultCubemapSceneWidget->resize(141, 279);
+        gridLayout = new QGridLayout(DefaultCubemapSceneWidget);
+#ifndef Q_OS_MAC
+        gridLayout->setSpacing(6);
+#endif
+        gridLayout->setMargin(0);
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        projectionGroup = new QGroupBox(DefaultCubemapSceneWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        gridLayout1 = new QGridLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        gridLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout1->setMargin(9);
+#endif
+        gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
+        gridLayout2 = new QGridLayout();
+#ifndef Q_OS_MAC
+        gridLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout2->setMargin(0);
+#endif
+        gridLayout2->setObjectName(QString::fromUtf8("gridLayout2"));
+        topFileNameEdit = new QLineEdit(projectionGroup);
+        topFileNameEdit->setObjectName(QString::fromUtf8("topFileNameEdit"));
+
+        gridLayout2->addWidget(topFileNameEdit, 4, 1, 1, 1);
+
+        frontFileNameEdit = new QLineEdit(projectionGroup);
+        frontFileNameEdit->setObjectName(QString::fromUtf8("frontFileNameEdit"));
+
+        gridLayout2->addWidget(frontFileNameEdit, 0, 1, 1, 1);
+
+        backBrowseButton = new QPushButton(projectionGroup);
+        backBrowseButton->setObjectName(QString::fromUtf8("backBrowseButton"));
+        QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(0));
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(backBrowseButton->sizePolicy().hasHeightForWidth());
+        backBrowseButton->setSizePolicy(sizePolicy);
+        backBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(backBrowseButton, 1, 2, 1, 1);
+
+        backFileNameEdit = new QLineEdit(projectionGroup);
+        backFileNameEdit->setObjectName(QString::fromUtf8("backFileNameEdit"));
+
+        gridLayout2->addWidget(backFileNameEdit, 1, 1, 1, 1);
+
+        bottomLabel = new QLabel(projectionGroup);
+        bottomLabel->setObjectName(QString::fromUtf8("bottomLabel"));
+
+        gridLayout2->addWidget(bottomLabel, 5, 0, 1, 1);
+
+        frontBrowseButton = new QPushButton(projectionGroup);
+        frontBrowseButton->setObjectName(QString::fromUtf8("frontBrowseButton"));
+        sizePolicy.setHeightForWidth(frontBrowseButton->sizePolicy().hasHeightForWidth());
+        frontBrowseButton->setSizePolicy(sizePolicy);
+        frontBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(frontBrowseButton, 0, 2, 1, 1);
+
+        leftLabel = new QLabel(projectionGroup);
+        leftLabel->setObjectName(QString::fromUtf8("leftLabel"));
+
+        gridLayout2->addWidget(leftLabel, 2, 0, 1, 1);
+
+        topBrowseButton = new QPushButton(projectionGroup);
+        topBrowseButton->setObjectName(QString::fromUtf8("topBrowseButton"));
+        sizePolicy.setHeightForWidth(topBrowseButton->sizePolicy().hasHeightForWidth());
+        topBrowseButton->setSizePolicy(sizePolicy);
+        topBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(topBrowseButton, 4, 2, 1, 1);
+
+        bottomFileNameEdit = new QLineEdit(projectionGroup);
+        bottomFileNameEdit->setObjectName(QString::fromUtf8("bottomFileNameEdit"));
+
+        gridLayout2->addWidget(bottomFileNameEdit, 5, 1, 1, 1);
+
+        topLabel = new QLabel(projectionGroup);
+        topLabel->setObjectName(QString::fromUtf8("topLabel"));
+
+        gridLayout2->addWidget(topLabel, 4, 0, 1, 1);
+
+        rightBrowseButton = new QPushButton(projectionGroup);
+        rightBrowseButton->setObjectName(QString::fromUtf8("rightBrowseButton"));
+        sizePolicy.setHeightForWidth(rightBrowseButton->sizePolicy().hasHeightForWidth());
+        rightBrowseButton->setSizePolicy(sizePolicy);
+        rightBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(rightBrowseButton, 3, 2, 1, 1);
+
+        bottomBrowseButton = new QPushButton(projectionGroup);
+        bottomBrowseButton->setObjectName(QString::fromUtf8("bottomBrowseButton"));
+        sizePolicy.setHeightForWidth(bottomBrowseButton->sizePolicy().hasHeightForWidth());
+        bottomBrowseButton->setSizePolicy(sizePolicy);
+        bottomBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(bottomBrowseButton, 5, 2, 1, 1);
+
+        rightLabel = new QLabel(projectionGroup);
+        rightLabel->setObjectName(QString::fromUtf8("rightLabel"));
+
+        gridLayout2->addWidget(rightLabel, 3, 0, 1, 1);
+
+        leftBrowseButton = new QPushButton(projectionGroup);
+        leftBrowseButton->setObjectName(QString::fromUtf8("leftBrowseButton"));
+        sizePolicy.setHeightForWidth(leftBrowseButton->sizePolicy().hasHeightForWidth());
+        leftBrowseButton->setSizePolicy(sizePolicy);
+        leftBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        gridLayout2->addWidget(leftBrowseButton, 2, 2, 1, 1);
+
+        frontLabel = new QLabel(projectionGroup);
+        frontLabel->setObjectName(QString::fromUtf8("frontLabel"));
+
+        gridLayout2->addWidget(frontLabel, 0, 0, 1, 1);
+
+        rightFileNameEdit = new QLineEdit(projectionGroup);
+        rightFileNameEdit->setObjectName(QString::fromUtf8("rightFileNameEdit"));
+
+        gridLayout2->addWidget(rightFileNameEdit, 3, 1, 1, 1);
+
+        leftFileNameEdit = new QLineEdit(projectionGroup);
+        leftFileNameEdit->setObjectName(QString::fromUtf8("leftFileNameEdit"));
+
+        gridLayout2->addWidget(leftFileNameEdit, 2, 1, 1, 1);
+
+        backLabel = new QLabel(projectionGroup);
+        backLabel->setObjectName(QString::fromUtf8("backLabel"));
+
+        gridLayout2->addWidget(backLabel, 1, 0, 1, 1);
+
+        spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        gridLayout2->addItem(spacerItem, 6, 1, 1, 1);
+
+
+        gridLayout1->addLayout(gridLayout2, 0, 0, 1, 1);
+
+
+        gridLayout->addWidget(projectionGroup, 0, 0, 1, 1);
+
+
+        retranslateUi(DefaultCubemapSceneWidget);
+
+        QMetaObject::connectSlotsByName(DefaultCubemapSceneWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *DefaultCubemapSceneWidget)
+    {
+        DefaultCubemapSceneWidget->setWindowTitle(QApplication::translate("DefaultCubemapSceneWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("DefaultCubemapSceneWidget", "Cubemap Properties", 0, QApplication::UnicodeUTF8));
+        backBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        bottomLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Bottom", 0, QApplication::UnicodeUTF8));
+        frontBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        leftLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Left", 0, QApplication::UnicodeUTF8));
+        topBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        topLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Top", 0, QApplication::UnicodeUTF8));
+        rightBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        bottomBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        rightLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Right", 0, QApplication::UnicodeUTF8));
+        leftBrowseButton->setText(QApplication::translate("DefaultCubemapSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        frontLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Front", 0, QApplication::UnicodeUTF8));
+        backLabel->setText(QApplication::translate("DefaultCubemapSceneWidget", "Back", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(DefaultCubemapSceneWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class DefaultCubemapSceneWidget: public Ui_DefaultCubemapSceneWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_DEFAULTCUBEMAPSCENEWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultemptyscenewidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultemptyscenewidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultemptyscenewidget.h	(revision 4)
@@ -0,0 +1,85 @@
+/********************************************************************************
+** Form generated from reading ui file 'defaultemptyscenewidget.ui'
+**
+** Created: Mon 27. Apr 14:23:52 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DEFAULTEMPTYSCENEWIDGET_H
+#define UI_DEFAULTEMPTYSCENEWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_DefaultEmptySceneWidget
+{
+public:
+    QVBoxLayout *vboxLayout;
+    QGroupBox *projectionGroup;
+    QVBoxLayout *vboxLayout1;
+    QLabel *label;
+
+    void setupUi(QWidget *DefaultEmptySceneWidget)
+    {
+        if (DefaultEmptySceneWidget->objectName().isEmpty())
+            DefaultEmptySceneWidget->setObjectName(QString::fromUtf8("DefaultEmptySceneWidget"));
+        DefaultEmptySceneWidget->resize(164, 141);
+        vboxLayout = new QVBoxLayout(DefaultEmptySceneWidget);
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+        vboxLayout->setMargin(0);
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        projectionGroup = new QGroupBox(DefaultEmptySceneWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        vboxLayout1 = new QVBoxLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        vboxLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout1->setMargin(9);
+#endif
+        vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+        label = new QLabel(projectionGroup);
+        label->setObjectName(QString::fromUtf8("label"));
+        label->setAlignment(Qt::AlignCenter);
+
+        vboxLayout1->addWidget(label);
+
+
+        vboxLayout->addWidget(projectionGroup);
+
+
+        retranslateUi(DefaultEmptySceneWidget);
+
+        QMetaObject::connectSlotsByName(DefaultEmptySceneWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *DefaultEmptySceneWidget)
+    {
+        DefaultEmptySceneWidget->setWindowTitle(QApplication::translate("DefaultEmptySceneWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("DefaultEmptySceneWidget", "Empty Properties", 0, QApplication::UnicodeUTF8));
+        label->setText(QApplication::translate("DefaultEmptySceneWidget", "(nothing, sorry!)", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(DefaultEmptySceneWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class DefaultEmptySceneWidget: public Ui_DefaultEmptySceneWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_DEFAULTEMPTYSCENEWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultmodelscenewidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultmodelscenewidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultmodelscenewidget.h	(revision 4)
@@ -0,0 +1,150 @@
+/********************************************************************************
+** Form generated from reading ui file 'defaultmodelscenewidget.ui'
+**
+** Created: Mon 27. Apr 14:23:53 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DEFAULTMODELSCENEWIDGET_H
+#define UI_DEFAULTMODELSCENEWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_DefaultModelSceneWidget
+{
+public:
+    QGridLayout *gridLayout;
+    QGroupBox *projectionGroup;
+    QGridLayout *gridLayout1;
+    QVBoxLayout *vboxLayout;
+    QHBoxLayout *hboxLayout;
+    QLabel *modelFileNameLabel;
+    QLineEdit *modelFileNameEdit;
+    QPushButton *modelBrowseButton;
+    QCheckBox *modelCullingCheckBox;
+    QCheckBox *modelSmoothingCheckBox;
+    QSpacerItem *spacerItem;
+
+    void setupUi(QWidget *DefaultModelSceneWidget)
+    {
+        if (DefaultModelSceneWidget->objectName().isEmpty())
+            DefaultModelSceneWidget->setObjectName(QString::fromUtf8("DefaultModelSceneWidget"));
+        DefaultModelSceneWidget->resize(179, 159);
+        gridLayout = new QGridLayout(DefaultModelSceneWidget);
+        gridLayout->setSpacing(0);
+        gridLayout->setMargin(0);
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        projectionGroup = new QGroupBox(DefaultModelSceneWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        gridLayout1 = new QGridLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        gridLayout1->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        gridLayout1->setMargin(9);
+#endif
+        gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(0);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        hboxLayout = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout->setMargin(0);
+#endif
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        modelFileNameLabel = new QLabel(projectionGroup);
+        modelFileNameLabel->setObjectName(QString::fromUtf8("modelFileNameLabel"));
+
+        hboxLayout->addWidget(modelFileNameLabel);
+
+        modelFileNameEdit = new QLineEdit(projectionGroup);
+        modelFileNameEdit->setObjectName(QString::fromUtf8("modelFileNameEdit"));
+
+        hboxLayout->addWidget(modelFileNameEdit);
+
+        modelBrowseButton = new QPushButton(projectionGroup);
+        modelBrowseButton->setObjectName(QString::fromUtf8("modelBrowseButton"));
+        QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(0));
+        sizePolicy.setHorizontalStretch(0);
+        sizePolicy.setVerticalStretch(0);
+        sizePolicy.setHeightForWidth(modelBrowseButton->sizePolicy().hasHeightForWidth());
+        modelBrowseButton->setSizePolicy(sizePolicy);
+        modelBrowseButton->setMaximumSize(QSize(23, 16777215));
+
+        hboxLayout->addWidget(modelBrowseButton);
+
+
+        vboxLayout->addLayout(hboxLayout);
+
+        modelCullingCheckBox = new QCheckBox(projectionGroup);
+        modelCullingCheckBox->setObjectName(QString::fromUtf8("modelCullingCheckBox"));
+
+        vboxLayout->addWidget(modelCullingCheckBox);
+
+        modelSmoothingCheckBox = new QCheckBox(projectionGroup);
+        modelSmoothingCheckBox->setObjectName(QString::fromUtf8("modelSmoothingCheckBox"));
+
+        vboxLayout->addWidget(modelSmoothingCheckBox);
+
+        spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout->addItem(spacerItem);
+
+
+        gridLayout1->addLayout(vboxLayout, 0, 0, 1, 1);
+
+
+        gridLayout->addWidget(projectionGroup, 0, 0, 1, 1);
+
+
+        retranslateUi(DefaultModelSceneWidget);
+
+        QMetaObject::connectSlotsByName(DefaultModelSceneWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *DefaultModelSceneWidget)
+    {
+        DefaultModelSceneWidget->setWindowTitle(QApplication::translate("DefaultModelSceneWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("DefaultModelSceneWidget", "Model Properties", 0, QApplication::UnicodeUTF8));
+        modelFileNameLabel->setText(QApplication::translate("DefaultModelSceneWidget", "File", 0, QApplication::UnicodeUTF8));
+        modelBrowseButton->setText(QApplication::translate("DefaultModelSceneWidget", "...", 0, QApplication::UnicodeUTF8));
+        modelCullingCheckBox->setText(QApplication::translate("DefaultModelSceneWidget", "Back face culling", 0, QApplication::UnicodeUTF8));
+        modelSmoothingCheckBox->setText(QApplication::translate("DefaultModelSceneWidget", "Smoothing", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(DefaultModelSceneWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class DefaultModelSceneWidget: public Ui_DefaultModelSceneWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_DEFAULTMODELSCENEWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultprojectorwidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultprojectorwidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultprojectorwidget.h	(revision 4)
@@ -0,0 +1,207 @@
+/********************************************************************************
+** Form generated from reading ui file 'defaultprojectorwidget.ui'
+**
+** Created: Mon 27. Apr 14:23:54 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DEFAULTPROJECTORWIDGET_H
+#define UI_DEFAULTPROJECTORWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_DefaultProjectorWidget
+{
+public:
+    QHBoxLayout *hboxLayout;
+    QGroupBox *projectionGroup;
+    QHBoxLayout *hboxLayout1;
+    QVBoxLayout *vboxLayout;
+    QHBoxLayout *hboxLayout2;
+    QLabel *fovLabel;
+    QLineEdit *fovEdit;
+    QLabel *aspectLabel;
+    QLineEdit *aspectRatioEdit;
+    QHBoxLayout *hboxLayout3;
+    QLabel *nearLabel;
+    QLineEdit *nearEdit;
+    QLabel *farLabel;
+    QLineEdit *farEdit;
+    QHBoxLayout *hboxLayout4;
+    QLabel *offaxisLabel;
+    QLabel *offaxisXLabel;
+    QLineEdit *offaxisXEdit;
+    QLabel *offaxisYLabel;
+    QLineEdit *offaxisYEdit;
+
+    void setupUi(QWidget *DefaultProjectorWidget)
+    {
+        if (DefaultProjectorWidget->objectName().isEmpty())
+            DefaultProjectorWidget->setObjectName(QString::fromUtf8("DefaultProjectorWidget"));
+        DefaultProjectorWidget->resize(164, 141);
+        hboxLayout = new QHBoxLayout(DefaultProjectorWidget);
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+        hboxLayout->setMargin(0);
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        projectionGroup = new QGroupBox(DefaultProjectorWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        hboxLayout1 = new QHBoxLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        hboxLayout1->setSpacing(6);
+#endif
+        hboxLayout1->setMargin(0);
+        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+        vboxLayout = new QVBoxLayout();
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+        vboxLayout->setMargin(4);
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        hboxLayout2 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout2->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout2->setMargin(0);
+#endif
+        hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+        fovLabel = new QLabel(projectionGroup);
+        fovLabel->setObjectName(QString::fromUtf8("fovLabel"));
+
+        hboxLayout2->addWidget(fovLabel);
+
+        fovEdit = new QLineEdit(projectionGroup);
+        fovEdit->setObjectName(QString::fromUtf8("fovEdit"));
+
+        hboxLayout2->addWidget(fovEdit);
+
+        aspectLabel = new QLabel(projectionGroup);
+        aspectLabel->setObjectName(QString::fromUtf8("aspectLabel"));
+
+        hboxLayout2->addWidget(aspectLabel);
+
+        aspectRatioEdit = new QLineEdit(projectionGroup);
+        aspectRatioEdit->setObjectName(QString::fromUtf8("aspectRatioEdit"));
+
+        hboxLayout2->addWidget(aspectRatioEdit);
+
+
+        vboxLayout->addLayout(hboxLayout2);
+
+        hboxLayout3 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout3->setSpacing(6);
+#endif
+        hboxLayout3->setMargin(0);
+        hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+        nearLabel = new QLabel(projectionGroup);
+        nearLabel->setObjectName(QString::fromUtf8("nearLabel"));
+
+        hboxLayout3->addWidget(nearLabel);
+
+        nearEdit = new QLineEdit(projectionGroup);
+        nearEdit->setObjectName(QString::fromUtf8("nearEdit"));
+
+        hboxLayout3->addWidget(nearEdit);
+
+        farLabel = new QLabel(projectionGroup);
+        farLabel->setObjectName(QString::fromUtf8("farLabel"));
+
+        hboxLayout3->addWidget(farLabel);
+
+        farEdit = new QLineEdit(projectionGroup);
+        farEdit->setObjectName(QString::fromUtf8("farEdit"));
+
+        hboxLayout3->addWidget(farEdit);
+
+
+        vboxLayout->addLayout(hboxLayout3);
+
+        hboxLayout4 = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout4->setSpacing(6);
+#endif
+        hboxLayout4->setMargin(0);
+        hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+        offaxisLabel = new QLabel(projectionGroup);
+        offaxisLabel->setObjectName(QString::fromUtf8("offaxisLabel"));
+
+        hboxLayout4->addWidget(offaxisLabel);
+
+        offaxisXLabel = new QLabel(projectionGroup);
+        offaxisXLabel->setObjectName(QString::fromUtf8("offaxisXLabel"));
+
+        hboxLayout4->addWidget(offaxisXLabel);
+
+        offaxisXEdit = new QLineEdit(projectionGroup);
+        offaxisXEdit->setObjectName(QString::fromUtf8("offaxisXEdit"));
+
+        hboxLayout4->addWidget(offaxisXEdit);
+
+        offaxisYLabel = new QLabel(projectionGroup);
+        offaxisYLabel->setObjectName(QString::fromUtf8("offaxisYLabel"));
+
+        hboxLayout4->addWidget(offaxisYLabel);
+
+        offaxisYEdit = new QLineEdit(projectionGroup);
+        offaxisYEdit->setObjectName(QString::fromUtf8("offaxisYEdit"));
+
+        hboxLayout4->addWidget(offaxisYEdit);
+
+
+        vboxLayout->addLayout(hboxLayout4);
+
+
+        hboxLayout1->addLayout(vboxLayout);
+
+
+        hboxLayout->addWidget(projectionGroup);
+
+        QWidget::setTabOrder(fovEdit, aspectRatioEdit);
+        QWidget::setTabOrder(aspectRatioEdit, nearEdit);
+        QWidget::setTabOrder(nearEdit, farEdit);
+
+        retranslateUi(DefaultProjectorWidget);
+
+        QMetaObject::connectSlotsByName(DefaultProjectorWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *DefaultProjectorWidget)
+    {
+        DefaultProjectorWidget->setWindowTitle(QApplication::translate("DefaultProjectorWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("DefaultProjectorWidget", "Projection", 0, QApplication::UnicodeUTF8));
+        fovLabel->setText(QApplication::translate("DefaultProjectorWidget", "FOV", 0, QApplication::UnicodeUTF8));
+        aspectLabel->setText(QApplication::translate("DefaultProjectorWidget", "Aspect", 0, QApplication::UnicodeUTF8));
+        nearLabel->setText(QApplication::translate("DefaultProjectorWidget", "Near", 0, QApplication::UnicodeUTF8));
+        farLabel->setText(QApplication::translate("DefaultProjectorWidget", "Far", 0, QApplication::UnicodeUTF8));
+        offaxisLabel->setText(QApplication::translate("DefaultProjectorWidget", "Off-axis ", 0, QApplication::UnicodeUTF8));
+        offaxisXLabel->setText(QApplication::translate("DefaultProjectorWidget", "X", 0, QApplication::UnicodeUTF8));
+        offaxisYLabel->setText(QApplication::translate("DefaultProjectorWidget", "Y", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(DefaultProjectorWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class DefaultProjectorWidget: public Ui_DefaultProjectorWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_DEFAULTPROJECTORWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultteapotscenewidget.h
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultteapotscenewidget.h	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/defaultplugin/ui_defaultteapotscenewidget.h	(revision 4)
@@ -0,0 +1,123 @@
+/********************************************************************************
+** Form generated from reading ui file 'defaultteapotscenewidget.ui'
+**
+** Created: Mon 27. Apr 14:23:55 2009
+**      by: Qt User Interface Compiler version 4.5.1
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DEFAULTTEAPOTSCENEWIDGET_H
+#define UI_DEFAULTTEAPOTSCENEWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QCheckBox>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QSpinBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_DefaultTeapotSceneWidget
+{
+public:
+    QGridLayout *gridLayout;
+    QGroupBox *projectionGroup;
+    QVBoxLayout *vboxLayout;
+    QHBoxLayout *hboxLayout;
+    QCheckBox *wireframeCheckBox;
+    QLabel *widthLabel;
+    QSpinBox *widthSpinBox;
+    QSpacerItem *spacerItem;
+
+    void setupUi(QWidget *DefaultTeapotSceneWidget)
+    {
+        if (DefaultTeapotSceneWidget->objectName().isEmpty())
+            DefaultTeapotSceneWidget->setObjectName(QString::fromUtf8("DefaultTeapotSceneWidget"));
+        DefaultTeapotSceneWidget->resize(227, 79);
+        gridLayout = new QGridLayout(DefaultTeapotSceneWidget);
+        gridLayout->setSpacing(0);
+        gridLayout->setMargin(0);
+        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+        projectionGroup = new QGroupBox(DefaultTeapotSceneWidget);
+        projectionGroup->setObjectName(QString::fromUtf8("projectionGroup"));
+        vboxLayout = new QVBoxLayout(projectionGroup);
+#ifndef Q_OS_MAC
+        vboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        vboxLayout->setMargin(9);
+#endif
+        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+        hboxLayout = new QHBoxLayout();
+#ifndef Q_OS_MAC
+        hboxLayout->setSpacing(6);
+#endif
+#ifndef Q_OS_MAC
+        hboxLayout->setMargin(0);
+#endif
+        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+        wireframeCheckBox = new QCheckBox(projectionGroup);
+        wireframeCheckBox->setObjectName(QString::fromUtf8("wireframeCheckBox"));
+
+        hboxLayout->addWidget(wireframeCheckBox);
+
+        widthLabel = new QLabel(projectionGroup);
+        widthLabel->setObjectName(QString::fromUtf8("widthLabel"));
+        widthLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+        hboxLayout->addWidget(widthLabel);
+
+        widthSpinBox = new QSpinBox(projectionGroup);
+        widthSpinBox->setObjectName(QString::fromUtf8("widthSpinBox"));
+        widthSpinBox->setMaximum(10);
+        widthSpinBox->setMinimum(1);
+        widthSpinBox->setValue(1);
+
+        hboxLayout->addWidget(widthSpinBox);
+
+
+        vboxLayout->addLayout(hboxLayout);
+
+        spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+        vboxLayout->addItem(spacerItem);
+
+
+        gridLayout->addWidget(projectionGroup, 0, 0, 1, 1);
+
+
+        retranslateUi(DefaultTeapotSceneWidget);
+        QObject::connect(widthLabel, SIGNAL(linkActivated(QString)), widthSpinBox, SLOT(selectAll()));
+
+        QMetaObject::connectSlotsByName(DefaultTeapotSceneWidget);
+    } // setupUi
+
+    void retranslateUi(QWidget *DefaultTeapotSceneWidget)
+    {
+        DefaultTeapotSceneWidget->setWindowTitle(QApplication::translate("DefaultTeapotSceneWidget", "Projection Settings", 0, QApplication::UnicodeUTF8));
+        projectionGroup->setTitle(QApplication::translate("DefaultTeapotSceneWidget", "Teapot Properties", 0, QApplication::UnicodeUTF8));
+        wireframeCheckBox->setText(QApplication::translate("DefaultTeapotSceneWidget", "Wireframe", 0, QApplication::UnicodeUTF8));
+        widthLabel->setText(QApplication::translate("DefaultTeapotSceneWidget", "Width", 0, QApplication::UnicodeUTF8));
+        widthSpinBox->setSuffix(QApplication::translate("DefaultTeapotSceneWidget", " px", 0, QApplication::UnicodeUTF8));
+        Q_UNUSED(DefaultTeapotSceneWidget);
+    } // retranslateUi
+
+};
+
+namespace Ui {
+    class DefaultTeapotSceneWidget: public Ui_DefaultTeapotSceneWidget {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_DEFAULTTEAPOTSCENEWIDGET_H
Index: projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.pro
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.pro	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.pro	(revision 4)
@@ -0,0 +1,2 @@
+TEMPLATE      = subdirs
+SUBDIRS       = defaultplugin
Index: projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.sln
===================================================================
--- projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.sln	(revision 4)
+++ projectionDesigner/trunk/projdesignerplugins/projdesignerplugins.sln	(revision 4)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "projdesigner_default", "D:/DA/Projection Designer/projdesigner_1.1.0/projdesignerplugins/defaultplugin\projdesigner_default.vcproj", "{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug|Win32
+		ConfigName.1 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Debug|Win32.Build.0 = Debug|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Release|Win32.ActiveCfg = Release|Win32
+		{6169FA3C-3764-3D1A-80FC-D97551D6C7AC}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: projectionDesigner/trunk/projection-designer-linux.pro
===================================================================
--- projectionDesigner/trunk/projection-designer-linux.pro	(revision 4)
+++ projectionDesigner/trunk/projection-designer-linux.pro	(revision 4)
@@ -0,0 +1,6 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+
+SUBDIRS += projdesignerplugins 
+SUBDIRS += projdesigner
