The application is composed of a series of .jpeg images. Each image represents the object at a different 10 degree angle. 36 pictures represent a full 360 degrees. 36 sets of pictures represent 360 degrees along both axis.
To create the images open Ulead Cool 3D and place an object on the design surface.
Click the Rotate button.
Then click the Add fixed transformation button (to reset the axis levels to zero).
In the Timeline, set 36 frames and 15 fps (frames per second).
Now click on the timeline bar and move it to frame 18.
Change the Y axis to 180 and click away.
The object will rotate 180 degrees
Move the timeline to 36 and enter 360 in the Y axis. The animation is now complete. Click the Play button (>) on the Navigation toolbar to preview the animation.
From the File menu on the toolbar, select Create Animation File, then Export to Macromedia Flash (SWF) then with JPEG.
Give the file the name 0_0.swf.
Open the .swf file you just created in SWF2XAML
Drag the scroll bar at the bottom all the way to the right. this will cause the program to create a folder called images and create 36 .jpegs.
In the File Renamer program, click the ... button to locate the images.
Select the option to Trim the first 7 characters of the files and then click the Rename Files button.
Now, select the numerate Files (## + extension) option and enter 00 in the Base digit to box. Click Rename Files.
Next, select Add... at 0 chars from name begin option and enter 00_ in the Rename to box and then click the Rename Files button.
The files will be renamed.
Place the files in a .zip file and call the .zip file Pictures.zip. Pictures.zip is used by the Silverlight application to load the pictures.
Repeat the process, this time move the X axis 10 degrees (you have to set it for all three points on the timeline in Cool 3D). Add all the pictures to the same Pictures.zip file.
The first 2 digits of the file names should be numbered according to the X axis (for example "01_02.jpeg").
Download the code and deploy the application. Replace the Pictures.zip in the downloaded code with the Pictures.zip you just created and you will then be able to rotate your image.
If you look at the XAML file in Expression Blend you will see the following:
The bar at the top is used to show the progress of the download of the Pictures.zip file. See this post for an explanation of the code.
The big square in the middle is a image control that has an X:Name of DisplayPicture. It has "mouse events" attached to it to fire JavaScript methods when it is clicked on.
<Image x:Name="DisplayPicture" Width="288" Height="281" Canvas.Left="211" Canvas.Top="78" Stretch="Uniform" Cursor="Hand" MouseLeftButtonDown="clickSelectedMouseDown" MouseLeftButtonUp="clickSelectedMouseUp" MouseMove="clickSelectedMouseMove"/>
<Canvas x:Name="sliderCanvasX" Width="240" Height="21" Canvas.Left="233" Canvas.Top="381">
<Canvas x:Name="sliderX"
Width="240" Height="21"
Background="transparent">
<Canvas x:Name="sliderThumbX" Width="20" Height="10" Canvas.Top="4.75"/>
</Canvas>
</Canvas>
All the functionality for the application is contained in the Page.xaml.js file:
1: //
2: // Original Silverlight VR Viewer Copyright (C) 2007 Jeff Paries
3: //
4: // DesignWithSilverlight.com
5: //
6: //
7: // 360 degree enhancements created by Michael Washington
8: // ADefWebserver.com
9: //
10:
11: if (!window.PictureDownloader)
12: window.PictureDownloader = {};
13:
14: PictureDownloader.Page = function()
15: {
16: }
17:
18: var glbPictures;
19: var glbsender;
20: var glbPictureIDX = 0;
21: var glbPictureIDY = 0;
22:
23: var mouseDownPosition = 0;
24: var mouseDownValue = -1;
25: var thumbCenterX;
26: var thumbCenterY;
27: var thumbWidth;
28: var totalFrames = 36;
29: var startFrame = 117;
30: var lastFrame = "image0";
31: var nextFrameCompleted = -1;
32: var scalingFactor;
33:
34: PictureDownloader.Page.prototype =
35: {
36: handleLoad: function(control, userContext, rootElement)
37: {
38: glbsender = rootElement;
39:
40: // calculate global variables
41: thumbWidth = rootElement.findName("sliderThumbX").width;
42: thumbCenterX = thumbWidth / 2;
43:
44: thumbWidth = rootElement.findName("sliderThumbY").width;
45: thumbCenterY = thumbWidth / 2;
46:
47: // set the initial position for the slider
48: var thumbX = rootElement.findName("sliderThumbX");
49: thumbX["Canvas.Left"] = startFrame;
50: newValueX = startFrame;
51:
52: var thumbY = rootElement.findName("sliderThumbY");
53: thumbY["Canvas.Top"] = startFrame;
54: newValueY = startFrame;
55:
56: var plugin = rootElement.getHost();
57: var downloader = plugin.createObject("downloader");
58:
59: downloader.addEventListener("downloadProgressChanged", onDownloadProgressChanged);
60: downloader.addEventListener("completed", onCompleted);
61:
62: downloader.open("GET", "Pictures.zip");
63: downloader.send();
64:
65: }
66:
67: }
68:
69: function doScale(sender, newValueX, newValueY)
70: {
71: glbPictureIDX = parseInt(newValueX / scalingFactor);
72:
73: if (glbPictureIDX > totalFrames)
74: {
75: glbPictureIDX = totalFrames;
76: }
77:
78: glbPictureIDY = parseInt(newValueY / scalingFactor);
79:
80: if (glbPictureIDY > totalFrames)
81: {
82: glbPictureIDY = totalFrames;
83: }
84:
85: SHOWPICTURE();
86: }
87:
88: // MOUSE MOVEMENT
89:
90: function clickSelectedMouseDown(sender, mouseEventArgs)
91: {
92: // mouse was clicked somewhere on the slider - move
93: // the slider thumb appropriately.
94: var coordinate = mouseEventArgs.getPosition(null);
95: var coordinateX = coordinate.x;
96: var coordinateY = coordinate.y;
97:
98: var sliderX = sender.findName("sliderCanvasX");
99: coordinateX -= sliderX["Canvas.Left"];
100: var sliderY = sender.findName("sliderCanvasY");
101: coordinateY -= sliderY["Canvas.Top"];
102:
103: mouseDownValue = 1;
104:
105: slider_SetValue(sliderX, coordinateX - thumbCenterX, coordinateY - thumbCenterY);
106: }
107:
108:
109: function clickSelectedMouseMove(sender, mouseEventArgs)
110: {
111: if (mouseDownValue != -1)
112: {
113: sender.captureMouse();
114: var coordinate = mouseEventArgs.getPosition(null);
115: var coordinateX = coordinate.x;
116: var coordinateY = coordinate.y;
117:
118: var sliderX = sender.findName("sliderCanvasX");
119: coordinateX -= sliderX["Canvas.Left"];
120: var sliderY = sender.findName("sliderCanvasY");
121: coordinateY -= sliderY["Canvas.Top"];
122:
123: slider_SetValue(sliderX, coordinateX - thumbCenterX, coordinateY - thumbCenterY);
124: }
125: }
126:
127: function clickSelectedMouseUp(sender)
128: {
129: sender.releaseMouseCapture();
130: mouseDownValue = -1;
131: }
132:
133:
134: // SLIDER
135:
136: function slider_SetValue(sender, newValueX, newValueY)
137: {
138: //Check if slider is at the maximum to the right
139: if (newValueX > sender.findName("sliderX").width)
140: {
141: newValueX = sender.findName("sliderX").width;
142: }
143:
144: //Check is slider is at the maximum to the left
145: if (newValueX <= 0)
146: {
147: newValueX = 0;
148: }
149:
150: //Check if slider is at the maximum to the bottom
151: if (newValueY > sender.findName("sliderY").height)
152: {
153: newValueY = sender.findName("sliderY").height;
154: }
155:
156: //Check is slider is at the maximum to the top
157: if (newValueY <= 0)
158: {
159: newValueY = 0;
160: }
161:
162: // calculate scaling values
163: doScale(sender, newValueX, newValueY);
164: }
165:
166:
167:
168:
169: //SHOW PICTURE
170:
171: function SHOWPICTURE()
172: {
173:
174: if(glbPictureIDX == totalFrames)
175: {
176: glbPictureIDX = (totalFrames - 1);
177: }
178:
179: if(glbPictureIDY == totalFrames)
180: {
181: glbPictureIDY = (totalFrames - 1);
182: }
183:
184: if(glbPictures != null)
185: {
186: var DisplayPicture = glbsender.findName("DisplayPicture");
187: var strPicture = PadDigits(glbPictureIDY,2) + "_" + PadDigits(glbPictureIDX,2) + ".jpg";
188:
189: //Note:
190: //We should find a way to simply check glbPictures
191: //and see if the image is in the .zip file
192: try
193: {
194: DisplayPicture.setSource(glbPictures, strPicture);
195: }
196: catch(errorObj)
197: {
198: //alert(errorObj.message);
199: DisplayPicture.Source = "NoImageFound.jpg";
200: }
201:
202: }
203:
204:
205: }
206:
207:
208: //DOWNLOADER
209:
210: function onDownloadProgressChanged(sender, eventArgs)
211: {
212: var plugin = sender.getHost();
213:
214: var percentage = Math.floor(sender.downloadProgress * 100);
215:
216: var progressText = plugin.content.findName("progressText");
217: var progressBar = plugin.content.findName("progressBar");
218:
219: progressText.text = percentage + "%";
220: progressBar.width = percentage * 4;
221: }
222:
223:
224: function onCompleted(sender, eventArgs)
225: {
226: var plugin = sender.getHost();
227: var myProgressBar = plugin.content.findName("myProgressBar");
228: myProgressBar.Opacity = 0;
229:
230: glbPictures = sender;
231:
232: scalingFactor = sender.findName("sliderX").width / totalFrames;
233: doScale(sender, newValueX, newValueY);
234: }
235:
236:
237: //Utility
238:
239: function PadDigits(n, totalDigits)
240: {
241: n = n.toString();
242: var pd = '';
243: if (totalDigits > n.length)
244: {
245: for (i=0; i < (totalDigits-n.length); i++)
246: {
247: pd += '0';
248: }
249: }
250: return pd + n.toString();
251: }
252:
Line 233 causes the application to create the first frame. When the mouse is clicked and dragged the methods under the "//MOUSE MOVEMENT" (line 88) are fired. They call the slider_SetValue method (line 136) that determines if either slider has been moved to the maximum level in either direction.
The slider_SetValue method calls the doScale method (line 69) that associates the slider position with a frame. This method then calls the SHOWPICTURE method (line 171) that retrieves the proper picture from the Pictures.zip file and displays it in the DisplayPicture control.
Back To: Silverlight Tutorials