You are not logged in.

Dear visitor, welcome to krpano.com Forum. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Sunday, June 13th 2010, 1:15pm

Object VR with left/right AND up/down rotation

There have been a couple of requests for multi-row object movies, so I've taken the liberty of modifying Klaus' objectskin.xml code to support rotations about both the Y and X axes. Klaus' original file can be found in the templates/xml/skin directory of the krpanotools 1.0.8.11 release. The new code allows one to turn the object not only left and right, but also up and down. It also supports user controllable autorotation (the autorotate.enabled, autorotate.waittime and autorotate.speed attributes are supported ). I've changed the code so that the user is not forced into panning mode when zoomed in, instead one can pan by pressing the space bar while moving the cursor. Please note that version 1.0.8.11 of the viewer is required as I make one use of the new square root function.

Note: This file is split across two posts due to the character length limitation of the forum. This is part 1 of 2 :

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<!--
	krpano 1.0.8.11
	object movie rotate/zoom/move example skin 
-->

<krpano version="1.0.8" onstart="objectvr_init()" >
	<!-- objectvr options
		xframes	[natural integer] the number of frames in each row (number of frames for a complete ath excursion)
		yframes	[natural integer] the number of frames in each column (number of frames for a complete atv excursion)
		startframe	[natural integer] the frame number for the initial view of the object
		hlimit	[boolean] limit the horizontal rotation (set to true for partial object vr's with limited atv rotation)
		autorotate	[boolean] enable autorotation, action objectvr_autorotate(); must be run after enabling
		autorotatedelay [float] time between frame updates for autorotation
	-->
	<objectvr />

	<autorotate speed="200.0" waittime="2" />

	<view fovtype="DFOV"
		limitview="fullrange"
		maxpixelzoom="1.0"
	/>

	<control zoomtocursor="true"
		zoomoutcursor="true"
		mousetype="moveto"
		mousespeed="0"
	/>

	<display flash10="on"
		movequality="HIGH" stillquality="HIGHSHARP"
		movequality10="HIGH" stillquality10="HIGH"
	/>

	<events onenterfullscreen="set(plugin[openfs].visible,false); set(plugin[closefs].visible,true);"
		onexitfullscreen ="set(plugin[openfs].visible,true);  set(plugin[closefs].visible,false);"
		onmousedown="objectvr_halt_autorotate();mdown();"
		onmouseup="mup();"
		onidle="objectvr_autorotate();"
		onkeydown="onkeydown();"
		onkeyup="onkeyup();"
		onresize="objectvr_update_panning();"
		onviewchange="if (objectvr.fullviewfov === null,
					if (view.fov != 90,
						copy(objectvr.fullviewfov,view.fov);
						roundval(objectvr.fullviewfov,1);
						set(events.onviewchange,null);
					);
				);"
	/>
	<action name="objectvr_init">
		if (objectvr.startframe !== null,
			copy(image.frame,objectvr.startframe);
		<!--else-->,
			div(image.frame,image.frames,2);
		);
		if (objectvr.yframes === null,
			if (objectvr.xframes === null,
				objectvr_guess_aspect_ratio();
				if (objectvr.xframes GT 72,
					if (objectvr.yframes == 1,
						error("pow function not available in this version of krpano, use 1.0.8.11 or newer OR set object.xframes");
					);
				);
			<!--else-->,
				div(objectvr.yframes,image.frames,objectvr.xframes);
				roundval(objectvr.yframes);
			);
		<!--else-->,
			if (objectvr.xframes === null,
				div(objectvr.xframes,image.frames,objectvr.yframes);
				roundval(objectvr.xframes);
			);
		);
		if (objectvr.xframes === null,
			div(objectvr.xframes,image.frames,objectvr.yframes);
			roundval(objectvr.xframes);
		);
		if (objectvr.yframes == 1,
			set(plugin[rotateupbg].visible,false);
			set(plugin[rotatedownbg].visible,false);
		);
		if (objectvr.xframes == 1,
			set(plugin[rotateleftbg].visible,false);
			set(plugin[rotaterightbg].visible,false);
		);
		if (objectvr.hlimit != true,
			set(objectvr.xframemax,1);
			copy(objectvr.xframemin,objectvr.xframes);
		<!--else-->,
			copy(objectvr.xframemax,objectvr.xframes);
			set(objectvr.xframemin,1);
		);
		sub(objectvr.yframemax,objectvr.yframes,1);
		sub(objectvr.xframe,image.frame,1);
		mod(objectvr.xframe,objectvr.xframes);
		inc(objectvr.xframe);
		div(objectvr.yframe,image.frame,objectvr.xframes);
		sub(objectvr.yframe,0.5);
		roundval(objectvr.yframe);
		div(objectvr.deltah,360,objectvr.xframes);
		copy(idletime,autorotate.waittime);
		copy(objectvr.autorotate,autorotate.enabled);
		set(autorotate.enabled,false);
		mul(objectvr.xmin,objectvr.yframe,objectvr.xframes);
		inc(objectvr.xmin);
		add(objectvr.xmax,objectvr.xmin,objectvr.xframes);
		dec(objectvr.xmax);
		objectvr_update_panning();
	</action>

	<action name="objectvr_guess_aspect_ratio">
		mul(objectvr.xframes,image.frames,2);
		inc(objectvr.xframes);
		pow(objectvr.xframes,0.5);
		dec(objectvr.xframes);
		roundval(objectvr.xframes);
		div(objectvr.yframes,image.frames,objectvr.xframes);
		roundval(objectvr.yframes);
		mul(action[%0].tmp,objectvr.xframes,objectvr.yframes);
		if (action[%0].tmp != image.frames,
			set(objectvr.xframes,36);
			div(objectvr.yframes,image.frames,objectvr.xframes);
			roundval(objectvr.yframes);
			set(action[%0].tryagain,false);
			if (objectvr.yframes GT 18,
				set(action[%0].tryagain,true);
			);
			mul(action[%0].tmp,objectvr.xframes,objectvr.yframes);
			if (action[%0].tmp != image.frames,
				set(action[%0].tryagain,true);
			);
			if (action[%0].tryagain,
				set(objectvr.xframes,48);
				div(objectvr.yframes,image.frames,objectvr.xframes);
				roundval(objectvr.yframes);
				set(action[%0].tryagain,false);
				if (objectvr.yframes GT 24,
					set(action[%0].tryagain,true);
				);
				mul(action[%0].tmp,objectvr.xframes,objectvr.yframes);
				if (action[%0].tmp != image.frames,
					set(action[%0].tryagain,true);
				);
				if (action[%0].tryagain,
					set(objectvr.yframes,1);
					copy(objectvr.xframes,image.frames);
				);
			);
		);
	</action>

	<!-- objectvr mouse rotate action -->
	<action name="mdown">
		if(control.mousespeed == 0,
			set(mbdown, true);
			set(xlastframepos,null);
			set(ylastframepos,null);
			objectrotate();
		);
	</action>

	<action name="mup">
		set(mbdown, false);
	</action>

	<action name="objectrotate">
		div(mxpos, mouse.x, stagewidth);
		mul(xframepos, mxpos, objectvr.xframes);
		roundval(xframepos);
		div(mypos, mouse.y, stageheight);
		mul(yframepos, mypos, objectvr.yframes);
		roundval(yframepos);

		if(xlastframepos == null, copy(xlastframepos,xframepos));
		if(ylastframepos == null, copy(ylastframepos,yframepos));

		sub(xframemove, xlastframepos, xframepos);
		copy(xlastframepos,xframepos);
		sub(yframemove, ylastframepos, yframepos);
		copy(ylastframepos,yframepos);

		set(xrotatedirection, right);
		if(xframemove LT 0, mul(xframemove,xframemove,-1); set(xrotatedirection, left); );
		set(yrotatedirection, up);
		if(yframemove LT 0, mul(yframemove,yframemove,-1); set(yrotatedirection, down); );
		if(mbdown,
			if(yframemove != 0,
				if(yrotatedirection == down,
					dec(objectvr.yframe,get(yframemove),0,0);
				,
					inc(objectvr.yframe,get(yframemove),get(objectvr.yframemax),get(objectvr.yframemax));
				);
				mul(objectvr.xmin,objectvr.yframe,objectvr.xframes);
				inc(objectvr.xmin);
				add(objectvr.xmax,objectvr.xmin,objectvr.xframes);
				dec(objectvr.xmax);
			);
			sub(objectvr.xframe,image.frame,1);
			mod(objectvr.xframe,objectvr.xframes);
			inc(objectvr.xframe);
			if(xframemove != 0,
				if(xrotatedirection == left,
					dec(objectvr.xframe,get(xframemove),1,get(objectvr.xframemin));
				,
					inc(objectvr.xframe,get(xframemove),get(objectvr.xframes),get(objectvr.xframemax));
				);
			);
			mul(action[%0].tmp,objectvr.yframe,objectvr.xframes);
			add(image.frame,action[%0].tmp,objectvr.xframe);

			delayedcall(0.01,objectrotate());
		);
	</action>

	<action name="startrotateleft">
		set(rotating,true);
		rotateleft();
	</action>

	<action name="startrotateright">
		set(rotating,true);
		rotateright();
	</action>

	<action name="startrotateup">
		set(rotating,true);
		rotateup();
	</action>

	<action name="startrotatedown">
		set(rotating,true);
		rotatedown();
	</action>

	<action name="rotateleft">
		if (objectvr.hlimit != true,
			dec(image.frame,1,get(objectvr.xmin),get(objectvr.xmax));
		<!--else-->,
			dec(image.frame,1,get(objectvr.xmin),get(objectvr.xmin));
		);
		delayedcall(0.02, if(rotating,rotateleft()) );
	</action>

	<action name="rotateright">
		if (objectvr.hlimit != true,
			inc(image.frame,1,get(objectvr.xmax),get(objectvr.xmin));
		<!--else-->,
			inc(image.frame,1,get(objectvr.xmax),get(objectvr.xmax));
		);
		delayedcall(0.02,  if(rotating,rotateright()) );
	</action>

	<action name="rotatedown">
		if (objectvr.yframe LT objectvr.yframemax,
			inc(objectvr.yframe,1,get(objectvr.yframes));
			inc(objectvr.xmin,get(objectvr.xframes));
			inc(objectvr.xmax,get(objectvr.xframes));
			inc(image.frame,get(objectvr.xframes));
		);
		delayedcall(0.02, if(rotating,rotatedown()) );
	</action>

	<action name="rotateup">
		if (objectvr.yframe GT 0,
			dec(objectvr.yframe,1,0);
			dec(objectvr.xmin,get(objectvr.xframes));
			dec(objectvr.xmax,get(objectvr.xframes));
			dec(image.frame,get(objectvr.xframes));
		);
		delayedcall(0.02,  if(rotating,rotateup()) );
	</action>

	<action name="stoprotate">
		set(rotating,false);
	</action>
Note: This file is split across two posts due to the character length limitation of the forum. This was part 1 of 2, see here for part 2
edit 6/19/10--various autorotate bug fixes and improvements per feedback from massimo and bags. Thanks guys!

This post has been edited 1 times, last edit by "pinsane" (Jun 19th 2010, 11:40am)


2

Sunday, June 13th 2010, 1:24pm

Note: This file is split across two posts due to the character length limitation of the forum. This is part 2 of 2, see here for part 1

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<action name="objectvr_autorotate">
		if (objectvr.autorotate == true,
			if (progress.isloading == true,
				delayedcall(1,objectvr_autorotate());
			<!--else-->,
				set(action[_objectvr_autorotate].halt,false);
				_objectvr_autorotate();
			);
		);
	</action>
	<action name="_objectvr_autorotate">
		if (objectvr.autorotate == true,
			oninterrupt(objectvr_halt_autorotate());
			if (action[%0].halt == true,
				set(action[%0].halt,false);
			<!--else-->,
				if (objectvr.hlimit != true,
					inc(image.frame,1,get(objectvr.xmax),get(objectvr.xmin));
				<!--else-->,
					if (action[%0].dir === null,
						set(action[%0].dir,right);
					);
					if (action[%0].dir == right,
						inc(image.frame,1,get(objectvr.xmax),get(objectvr.xmax));
						if (image.frame GE objectvr.xmax,
							set(action[%0].dir,left);
						);
					<!--else-->,
						dec(image.frame,1,get(objectvr.xmin),get(objectvr.xmin));
						if (image.frame LE objectvr.xmin,
							set(action[%0].dir,right);
						);
					);
				);
				div(objectvr.autorotatedelay,objectvr.deltah,autorotate.speed);
				if (objectvr.autorotatedelay LT 0, <!--BUGFIX strange, somtimes autorotate.speed is negative-->
					mul(objectvr.autorotatedelay,-1);
				);
				delayedcall(get(objectvr.autorotatedelay),_objectvr_autorotate());
			);
		);
	</action>

	<action name="onkeydown">
		if (keycode == 32,
			set(control.mousespeed,10);
			set(control.mousetype,drag2d);
			copy(action[%0].fov,view.fov);
			roundval(action[%0].fov,1);
			if (action[%0].fov GE objectvr.fullviewfov,
				showtext("you must first zoom in order to pan");
			);
<!--uncomment these lines to use hand cursor for dragging (see also onkeyup)
			set(cursors.url, skin/drag-cursors.png);
			set(cursors.type, drag);
			set(cursors.move,  2|0|30|32);
			set(cursors.drag, 37|0|30|32);
-->
		<!--else-->,
			if (keycode == 16,
				objectvr_halt_autorotate();
			<!--else-->,
				if (keycode == 17,
					objectvr_halt_autorotate();
				<!--else-->,
					if (keycode == 37,
						objectvr_halt_autorotate();
					<!--else-->,
						if (keycode == 38,
							objectvr_halt_autorotate();
						<!--else-->,
							if (keycode == 39,
								objectvr_halt_autorotate();
							<!--else-->,
								if (keycode == 40,
									objectvr_halt_autorotate();
								);
							);
						);
					);
				);
			);
		);
	</action>

	<action name="onkeyup">
		if (keycode == 32,
			set(control.mousespeed,0);
			set(control.mousetype,moveto);
<!--uncomment these lines to use hand cursor for dragging (see also onkeydown)
			set(cursors.url,null);
-->
		<!--else-->,
			if (keycode == 16,
				objectvr_update_panning();
			<!--else-->,
				if (keycode == 17,
					objectvr_update_panning();
				);
			);
		);
	</action>

	<action name="showup_rotate_buttons">
		tween(plugin[rotaterightbg].alpha, 0.7, 1.5, easeOutQuad, tween(plugin[rotaterightbg].alpha, 0.0, 2.5, easeInExpo));
		tween(plugin[rotateleftbg].alpha,  0.7, 1.5, easeOutQuad, tween(plugin[rotateleftbg].alpha,  0.0, 2.5, easeInExpo));
		tween(plugin[rotateupbg].alpha, 0.7, 1.5, easeOutQuad, tween(plugin[rotateupbg].alpha, 0.0, 2.5, easeInExpo));
		tween(plugin[rotatedownbg].alpha,  0.7, 1.5, easeOutQuad, tween(plugin[rotatedownbg].alpha,  0.0, 2.5, easeInExpo));
	</action>

	<action name="objectvr_halt_autorotate">
		set(action[_objectvr_autorotate].halt,true);
		invalidatescreen();
	</action>

	<action name="objectvr_update_panning">
		copy(action[%0].tmp,view.hfov);
		roundval(action[%0].tmp,2);
		if (action[%0].tmp LT 1,
			set(plugin[left].alpha,1);
			set(plugin[right].alpha,1);
		<!--else-->,
			set(plugin[left].alpha,0.3);
			set(plugin[right].alpha,0.3);
		);
		copy(action[%0].tmp,view.vfov);
		roundval(action[%0].tmp,2);
		if (action[%0].tmp LT 1,
			set(plugin[up].alpha,1);
			set(plugin[down].alpha,1);
		<!--else-->,
			set(plugin[up].alpha,0.3);
			set(plugin[down].alpha,0.3);
		);
	</action>
	<textstyle name="buttonstyle" font="Arial" fontsize="12" bold="true" italic="true"
		textcolor="0x000000" background="false" border="false"
		blendmode="layer" effect="glow(0xFFFFFF,0.85,4,4);dropshadow(2,45,0x000000,4,1);"
		origin="cursor" edge="bottom" xoffset="15" yoffset="-5" showtime="0.1" fadeintime="0.1" fadetime="0.1"
	/>

	<style name="button" url="%SWFPATH%/skin/buttons.png" zorder="3" keep="true" />

	<plugin name="in"       align="bottom" x="-140" y="10" style="button" crop="160|0|40|40" onovercrop="160|40|40|40" ondowncrop="160|80|40|40" onhover="showtext('Zoom IN ', buttonstyle);"   ondown="objectvr_halt_autorotate();set(movevectorz,-1);"  onup="set(movevectorz,0);objectvr_update_panning();" />
	<plugin name="out"      align="bottom" x="-100"  y="10" style="button" crop="200|0|40|40" onovercrop="200|40|40|40" ondowncrop="200|80|40|40" onhover="showtext('Zoom OUT ', buttonstyle);"  ondown="objectvr_halt_autorotate();set(movevectorz,+1);"  onup="set(movevectorz,0);objectvr_update_panning();" />
	<plugin name="left"     align="bottom" x="-60"  y="10" style="button" crop=  "0|0|40|40" onovercrop=  "0|40|40|40" ondowncrop=  "0|80|40|40" onhover="showtext('Pan Left ', buttonstyle);"  ondown="objectvr_halt_autorotate();set(movevectorx,-1);"  onup="set(movevectorx,0);" />
	<plugin name="right"    align="bottom" x="-20"    y="10" style="button" crop= "40|0|40|40" onovercrop= "40|40|40|40" ondowncrop= "40|80|40|40" onhover="showtext('Pan Right ', buttonstyle);" ondown="objectvr_halt_autorotate();set(movevectorx,+1);"  onup="set(movevectorx,0);" />
	<plugin name="up"       align="bottom" x="+20"  y="10" style="button" crop= "80|0|40|40" onovercrop= "80|40|40|40" ondowncrop= "80|80|40|40" onhover="showtext('Pan Up ', buttonstyle);"    ondown="objectvr_halt_autorotate();set(movevectory,-1);"  onup="set(movevectory,0);" />
	<plugin name="down"     align="bottom" x="+60"  y="10" style="button" crop="120|0|40|40" onovercrop="120|40|40|40" ondowncrop="120|80|40|40" onhover="showtext('Pan Down ', buttonstyle);"  ondown="objectvr_halt_autorotate();set(movevectory,+1);"  onup="set(movevectory,0);" />
	<plugin name="autorotate"     align="bottom" x="+100"  y="10" style="button" crop="240|0|40|40" onovercrop="240|40|40|40" ondowncrop="240|80|40|40" onhover="showtext('Toggle Autorotate ', buttonstyle);"  onclick="switch(objectvr.autorotate);objectvr_autorotate();" />
	<plugin name="openfs"   align="bottom" x="+140" y="10" style="button" crop="280|0|40|40" onovercrop="280|40|40|40" ondowncrop="280|80|40|40" onhover="showtext('Fullscreen ', buttonstyle);"      onclick="set(fullscreen,true);"  visible="true"  />
	<plugin name="closefs"  align="bottom" x="+140" y="10" style="button" crop="320|0|40|40" onovercrop="320|40|40|40" ondowncrop="320|80|40|40" onhover="showtext('Exit Fullscreen ',buttonstyle);"  onclick="set(fullscreen,false);" visible="false" />


	<plugin name="rotaterightbg" url="%SWFPATH%/skin/black.png" align="right" width="125" height="100%" alpha="0.0" zorder="1" onover="tween(plugin[rotaterightbg].alpha,0.7);" onout="tween(plugin[rotaterightbg].alpha,0);" ondown="objectvr_halt_autorotate();startrotateleft();"  onup="stoprotate();" />
	<plugin name="rotateleftbg"  url="%SWFPATH%/skin/black.png" align="left"  width="125" height="100%" alpha="0.0" zorder="1" onover="tween(plugin[rotateleftbg].alpha,0.7);"  onout="tween(plugin[rotateleftbg].alpha,0);"  ondown="objectvr_halt_autorotate();startrotateright();" onup="stoprotate();" />
	<plugin name="rotateupbg" url="%SWFPATH%/skin/black.png" align="top" width="100%" height="125" alpha="0.0" zorder="1" onover="tween(plugin[rotateupbg].alpha,0.7);" onout="tween(plugin[rotateupbg].alpha,0);" ondown="objectvr_halt_autorotate();startrotatedown();"  onup="stoprotate();" />
	<plugin name="rotatedownbg"  url="%SWFPATH%/skin/black.png" align="bottom" width="100%" height="125" alpha="0.0" zorder="1" onover="tween(plugin[rotatedownbg].alpha,0.7);"  onout="tween(plugin[rotatedownbg].alpha,0);"  ondown="objectvr_halt_autorotate();startrotateup();" onup="stoprotate();" />

	<plugin name="rotaterighticon" url="%SWFPATH%/skin/arrow.png" align="right" x="10" scale="0.5" zorder="2" enabled="false" parent="rotaterightbg" />
	<plugin name="rotatelefticon"  url="%SWFPATH%/skin/arrow.png" align="left" edge="right" rotate="180" x="10" scale="0.5" zorder="2" enabled="false"  parent="rotateleftbg" />
	<plugin name="rotateupicon" url="%SWFPATH%/skin/arrow.png" align="top" edge="right" y="10" scale="0.5" rotate="-90" zorder="2" enabled="false" parent="rotateupbg" />
	<plugin name="rotatedownicon"  url="%SWFPATH%/skin/arrow.png" align="bottom" edge="right" rotate="90" y="60" scale="0.5" zorder="2" enabled="false"  parent="rotatedownbg" />

</krpano>
Note: This file is split across two posts due to the character length limitation of the forum. This was part 2 of 2, see here for part 1
edit 6/19/10--various autorotate bug fixes and improvements per feedback from massimo and bags. Thanks guys!

This post has been edited 1 times, last edit by "pinsane" (Jun 19th 2010, 11:44am)


3

Sunday, June 13th 2010, 2:07pm

The object VR is composed of a series of photographs that are ordered in a specific manner that allows the action to properly access a specific picture. These photos are ordered by name, a simple way to do this is to name them pic0001.tif, pic0002.tif, pic0003.tif, etc. The kmakemultires program uses the names of the file supplied to put the frames in order.

When naming your files, you should use leading zero padding in your name, that is, all numbers should be represented by the same number of digits, using leading zeros to fill out the number. For example, if you have 196 pictures, your numbers should always be represented with 3 digits (because 196 uses three digits). Thus name your files image001.tif, image002.tif, ... ,image009.tif,image010.tif,image011.tif, ... ,image099.tif,image100.tif,image101.tif, ... ,image191.tif,image192.tif. Because kmakemultires sorts the file names using alphabetic sorting, files named using leading zeros will be sorted correctly and produce the proper ordering for your frames. If you instead choose to name things image1.tif, image2.tif, ... ,image191.tif,image192.tif, the current versions of kmakemultires (1.0.8.10 or 1.0.8.11) will incorrectly sort your frames image1.tif,image10.tif,image11.tif,image12.tif, etc.

For a 2 axes object vr, we can consider the pictures to be organized in a grid. Each row of the grid contains a complete counterclockwise revolution around the object at a given altitude. Each column of the grid contains a vertical transition from a high altitude (limited by -90 degrees--the top of the object) to a low altitude (limited by 90 degrees--the bottom of the object). To use an analogy with a standard panorama each row contains all pictures with a given ath while each column contains all pictures with a particular atv. Each picture is names starting from the upper left corner, moving across each row and then returning to the leftmost column of the next row when a given row is completed.

Let's call the angle change between each picture in a row deltah; this is the incremental angle change about the y axis. We'll refer to the angle changes in each column as deltav; this is the incremental angle change about the x axis. The smaller the angle change between pictures, the smoother the objectvr will turn but the larger the number of pictures that need to be captured. 360 must be evenly divisible by the horizontal angle between pictures (ie. 360/deltah must be an integer) to avoid jerkiness when rotating around the object. Similarly 180 must be evenly divisible by the vertical angle between pictures (ie 180/deltav must be an integer). Many people use 10 degrees as the delta angle, but I prefer the smoother 7.5 degrees.

If you wish to provide full coverage of an object (a view from every perspective), and want the deltav to equal the deltah (which provides uniform rotations in each direction) then the number of photographs required is:
number of pictures per row = 360/deltah
number of pictures per column = 180/deltav+1
The +1 for the column is required because you don't wrap all the way around the sphere, so to get coverage of both the top and bottom of the object, you need to add 1 row.

Here's the layout and numbering of the pictures for a 7.5 degree example:

Source code

1
2
3
4
5
6
7
8
9
10
atv\ath    -172.5	   -165.0	  -157.5	...	      0		...	   165.0	   172.6	   180
-90.0	pic0001.tif	pic0002.tif	pic0003.tif	...	pic0024.tif	...	pic0046.tif	pic0047.tif	pic0048.tif
-82.5	pic0049.tif	pic0050.tif	pic0051.tif	...	pic0072.tif	...	pic0094.tif	pic0095.tif	pic0096.tif
-75.0	pic0097.tif	pic0098.tif	pic0099.tif	...	pic0120.tif	...	pic0142.tif	pic0143.tif	pic0144.tif
 ...        ...		     ...	     ...	...	     ...	...	     ...	     ...	     ...
   0	pic0577.tif	pic0578.tif	pic0579.tif		pic0600.tif	...	pic0622.tif	pic0623.tif	pic0624.tif
 ...        ...		     ...	     ...	...	     ...	...	     ...	     ...	     ...
 75.0	pic1057.tif	pic1058.tif	pic1059.tif	...	pic1080tif	...	pic1102.tif	pic1103.tif	pic1104.tif
 82.5	pic1105.tif	pic1106.tif	pic1107.tif	...	pic1128.tif	...	pic1150.tif	pic1151.tif	pic1152.tif
 90.0	pic1153.tif	pic1154.tif	pic1155.tif	...	pic1176.tif	...	pic1998.tif	pic1999.tif	pic1200.tif


Given that each photograph is taken 7.5 degrees apart, the size of the grid is 48 photographs wide (48 * 7.5 = 360 degrees) and 25 photos up and down. 25 photos are needed to cover from zenith to nadir (24 * 7.5 = 180 degrees plus one extra so that both the zenith and nadir are covered).

Each row of photographs starts from behind the object of interest (atv = -172 degrees), travels around the object in a counterclockwise manner and finishes exactly behind the object at (atv = 180 degrees). If you sequence through the photographs in any row it will appear that the object is turning clockwise 360 degrees from a constant altitude.

Each column shows the same atv value for the object, but goes from top (ath=-90) to bottom (ath=90) in 7.5 degree increments.

Once every picture is properly named, you can use kmakemultires with the object.config file found in the templates directory. I've found that in windows, you can't use the droplet with a large number of files, so using the command line version is necessary.

Good luck!

steve

michel

Professional

Posts: 1,153

Location: ANDORRA

Occupation: TV

  • Send private message

4

Monday, June 14th 2010, 12:58am

Hi Steve,

That seems to be exciting *smile* , an other great effort of yours *thumbup* ... The only problem is that I have no full 360 object to try the code *rolleyes* ... So, I am waiting to see a resulting example from some one *squint* ...

SAlut.

VN2009

Professional

Posts: 1,336

Location: Duluth MN

  • Send private message

5

Monday, June 14th 2010, 2:06am

another great contibution Pinsane, Thank You!

Tuur

Sage

Posts: 3,105

Location: Netherlands

Occupation: Krpano custom coding / Virtual Tours / Photography / Musician / Recording engineer

  • Send private message

6

Monday, June 14th 2010, 10:40am

...

I think we upgrade Pinsane to professional.. Klaus?

Great!

Thanx Steve for your great TuT again *thumbup*
You get a full weekend free drinks in the 'bar'.

Cheers

Tuur *thumbsup*
http://www.virtualtuur.com
Skype:studiotuur

bulp

Intermediate

Posts: 389

Location: Malaysia

  • Send private message

7

Monday, June 14th 2010, 2:19pm

Thank you very much Pinsane!! *thumbsup*

8

Tuesday, March 29th 2011, 4:24am

how to have full 360 in both horiz and vert orientations?

hi there --

awesome (and working) code example... many thanks!

i don't see, easily, how to have a full 360 rotation in vertical orientation. i have an object which will need to rotate fully vertically, and limited horizontally. Ideas? A pointer to what to modify in the code would be fine -- it appears to me to limit the y rotation by default, to the number of rows minus 1. *question*

thanks in advance!

9

Sunday, May 8th 2011, 9:32am

Great job!

I tested it and works great for me! thanks so much Pinsane!! you're the best. *thumbsup* *squint*
 

*whistling* mail: Bludream@gmail.com,

bulp

Intermediate

Posts: 389

Location: Malaysia

  • Send private message

10

Sunday, June 5th 2011, 4:47am

bludream would u share the sample working demo ?

danimorgo

Beginner

Posts: 42

Location: argentina

Occupation: diseñador

  • Send private message

11

Saturday, October 19th 2013, 3:09am

is there any link to view an example

Posts: 1,081

Location: Russia, Kaliningrad

  • Send private message

12

Saturday, April 16th 2016, 10:10pm

VRAP - desktop VR content player based on krpano.
Common tasks in one place in one click! Discussion thread
DOWNLOAD for MAC
DOWNLOAD for WIN

samadi

Beginner

Posts: 28

Location: Iran

Occupation: Tehran,Alborz,nazarabad,

  • Send private message

13

Saturday, September 9th 2017, 3:22pm

this is an old example of 360 degree rotation object
http://livepano.ir/images/vr/sony360/html5/3600-3600.html
samadi
http://www.livepano.ir

Similar threads