C++
Tutorial
Part 3c
3D Visualization of Pagehits by Hour
and Animated over a Day

Download this file:

Animation-3D.zip is actually two seperate visualizations, although the code was so similar between them that I used the same program, and you choose with compiler directive which visualzation you are creating. Did I need to go to the trouble of using compiler directives? No. I just think they're fun. I could have instead set it with a command line parameter.

The non-animated 3D view looks like this:

This shows the page on the z-axis, the time of day on the x-axis and the hit count on the y-axis. This data is for January 3, 2003. The animated version of this cycles through January 1 - January 3.

Below are excerpts of the code with a description of what it does.

--Begin Code--

We start off by either defining AnimationMode at compile time or not. This is the flag which tells the compiler whether we want to build the animation or not

//#define AnimationMode

Here we check to see if it is in animation mode or not. If it is we use AnimationData.txt for input, otherwise use 3dPlotData.txt

#ifdef AnimationMode
   char inputFilename[] = "AnimationData.txt\0";
#else
   char inputFilename[] = "3dPlotData.txt\0";
#endif

Following is a struct which is used to hold a reference to all the object displayed in the visualization. This is needed for the animation. Note that I have hard coded the array sizes. This is hard fixed so that it can only display three pages per day across a three hour period of time. I could have made it dynamic so that it could show as many pages across as many hour periods as I wanted, however this would have required me to have created pointers to pointers, thus vtkTextSource *text[3] would be written as vtkTextSource **text. While I have used pointers to pointers before, doing so gets really messy so I chose not to do so for this program.

struct DayStruct {
   char page1[256];
   char page2[256];
   char page3[256];

   int hitCount[9];

   vtkTextSource *text[3];
   vtkPolyDataMapper *textMapper[3];
   vtkActor *textActor[3];

   vtkTextSource *hourText[3];
   vtkPolyDataMapper *hourTextMapper[3];
   vtkActor *hourTextActor[3];

   vtkCylinderSource *cylinder[9];
   vtkPolyDataMapper *cylinderMapper[9];
   vtkActor *cylinderActor[9];
};

Here we create an array of DayStructs. Each element corresponds to a different day in the animation.

DayStruct Days[3];

Below is where the actual rendering takes place. If we are not in animation mode we display the first day and leave it at that. However is we are in animation mode then we enter an endless loop where we display a day, then sleep for half a second. Unload the day from the visualization then load the next day. At the same time we increase the camera's azimuth by 5. This makes the scene rotate by 5 degrees every time it is redrawn.

LoadAxes(ren1);
DisplayDay(&Days[0], 0, ren1);
renWin->Render();

#ifdef AnimationMode

i = 0;
while(true)
{
   DisplayDay(&Days[0], i, ren1);

   ren1->GetActiveCamera()->Azimuth(5);
   renWin->Render();
   Sleep(500);
   UnloadDay(&Days[0], i, ren1);
   renWin->Render();
   Sleep(100);

   i++;
   if (i > 2)
      i = 0;
}
#endif

--End Code--

Obviously I didn't even show 1/3 of the code required to make this visualization. I figured that by this point how the other actions were performed should be elementary. As the only objects this scene uses are textActors and cylinderActors it is rather easy to create and position them. Then to display the actors you just loop through the array of actors and add them to the renderer. Alternately to remove them you just loop through the array of actors and remove them from the renderer.

Home
C++ Tutorial
Python Tutorial
TCL/TK Tutorial

Downloads
Homework
About Us
Contact
Links

C++ Tutorial
Part 1: VS 6
Part 2: VS .NET
Part 3: SUU Logs