## Part VII – Panorama hotspot interaction, light up on mouse over

With respect to the previous post (part VI), only a few minor changes were required to the demo we had so far. Basically making the hotspot light up is implemented by drawing on the plane’s material. That’s all there is to it. I’ve implemented this idea in the interactive material class.

Lots of room for optimization, but the basic principle remains the same.

Although the goal has never been to deliver a set of reusable classes/components, the basics are all there, and the possibilities are legion. And although the architecture of the code samples can be improved, and they are far from being a complete application, most of the principles and a lot of the sources can be reused and applied to your own panorama implementations. Also note that you might need to clean the code a bit (I saw some left over parameters sneaking around that are no longer used, hunt them down!).

## Part VI – Panorama hotspot interaction

How you define your hotspots is up to you. For example you could write a tool which allows you to edit and generate a CubicPanorama. For a project for the dutch police academy I’m currently working on at TriMM, I am writing such an editor in Flex. Here is a screenshot of the work in progress:

Basically it allows you to select a cube side, import a picture for it and draw hotspots on it. The complete definition/model for the cube is then saved to xml, the polygon information with it.

In this demo I’m simply generating rectangular hotspots on the fly randomly as you can see when you reload the page. No matter whether you are using irregular shapes through xml or random rectangles the principle stays the same.

## Part V – Mouse to Plane coordinates, second step to implementing panorama hotspots

In the previous post, we implemented a vector pointing at the cube plane under your mouse. In this post we will look at deriving the local x,y coordinate within that plane, and with it the local x,y coordinate of the pixel within the plane’s texture under your mouse. (Although for hotspots, any local coordinate system will do).

In order to do so, we need to project the vector at the plane it is pointing at. This results in a coordinate that lies within the plane. The coordinate comes from a set of coordinates that all lie within that plane, and this set can be mapped to a range representing the texture coordinates (or hotspot coordinates as we will see later). Although this might sound complicated, it is not so bad as it sounds.

## Part IV – Plane detection, a first step to implementing panorama hotspots

In order to be able to detect hotspots under the mouse, the first thing we need to do is find some way to detect which plane the mouse is currently over and what the local x,y coordinates of the mousecursor are in the local space of that plane.

Instead of providing all the theoretical background I want to try and make it conceptually clear how we can do this. So let go of the mouse coordinates for a moment and take a look at our untransformed starting cube we discussed in a previous post:

## Part III – Externalizing the panorama assets

There is an issue with distributing source code for your demo’s. Besides demonstrating what you want to demonstrate, you give people a look at how you program. But the focus is not how I program, it’s demonstrating the concepts of creating interactive panorama’s with hotspots that light up. This means I have to find some middle ground in which the code is kept to the bare minimum without hardly any framework classes or complex program structures, while keeping the example readable and extensible.

Therefore I decided to open this post with a little information on application structures. Probably one of the hardest parts of programming is rising to/with the correct level of complexity. You want to be prepared for anything, but not over complicate things (KISS).

So what do you choose for your application structure? You can choose one of the many frameworks, or you can roll with your own. And after that, do you apply that framework to any application you write?

Personally I love to use a setup which allows me to refactor fast, so I can keep the application as simple as possible and then go more complex when needed. This might not always be preferable when working with larger teams, but for these tutorials, for me it is a nice way to work.

## Part II – Improved Panorama

In the previous panorama post I mentioned a number of issues that would have to be fixed. For this demo I used another image from http://www.flickr.com/photos/heiwa4126/, who has a set of amazing images, so it’s really worth to go there and take a look (the other images in the flickr equirectangular group are very good as well btw).

So in no particular order, what did we add/fix in this version?

Clipping
The clipping issue was described in the previous post.

Seams
The seams were a surprise to me. I thought the render process caused the seams, and that I would have to fix it by making the planes slightly overlap however, that didn’t fix it, it only made things worse. Then I discovered that the seams were caused by the bitmapfill repeat parameter which was set to true, when smoothing was turned on for the planes. If you remember, this setting was switched on to prevent drawing lag when points crossed the diagonal of drawn triangle. Since that will never happen when rendering the inside of a cube with our field of view setting, we can safely turn it off. And poof ! No more seams.

(Fluid) motion
I updated the mouse and key movement and added mass. The slight delay after you press a key is now gone as well. See the render function for more info on this.

Correct rotation
The rotation is correct. In order to implement that, we needed to keep the original points untransformed, and store a transformed copy of those points as well. Using two rotation matrices, one for x and one for the y direction, we can correctly transform these points each render pass (but only if we have moved).

Field of vision
I implemented a somewhat more scientific way of calculating the projection plane distance based on a field of view parameter. Please refer to the sources for more info.

What’s next?
We fixed a number of minor other stuff as well and cleaned the code a bit, so we are slowly getting to where we want to be. In the next version I will refactor the DistortedPlane class into a more specific custom PanoCubeSide class to make the performance even better, although I think that for actionscript 2 it is pretty solid already.

In addition we will look at externalizing the images and the implementation of hotspots in the next version!

## Part Ib – Intermezzo Improved Quad Clipping

You may or may not have noticed, but the clipping procedure in the DistortedPlane class we’ve been using can be improved, since it allows for false negatives. This is demonstrated when turning around fast in the panorama from the previous post: white triangles (or whatever your background color is) will pop up.

What is going on?
Basically our clipping method tests whether one of the four corner points of the quad-to-render is within the clipped region. If true, render, if false, skip. That test is very easy to understand: “hey part of me is within the visible region, so render me!” Unfortunately it is also very wrong.

Take a look at the following image:

## Part I – Panorama prototype

So, after all the posts about rendering image planes we are finally getting to our first panorama implementation. You can test version 0.1 on the left, but be sure to read the ‘Issues’ section for an overview of stuff to fix in the next versions.

Basically it is nothing more than just another cube like we had in the previous example, but now the cube is centered around our camera at (0,0,0) and we are looking at the planes on the inside of the cube.

## Part IVc – Intermezzo Automatic Mesh Density Reduction

One of the things I wanted to try was to automatically reduce the mesh density of a plane based on it’s current size. So instead of determining beforehand that a plane has to have 6 by 6 subdivision, you would simply say something like make sure no subdivision is bigger than 30 x 30 pixels.

In effect it’s a very simple LOD modifier or Level of Size modifier if you will.

Is this usable? Well there are a number of considerations: