Cylinder style 3d list

Blitz3D Forums/Blitz3D Beginners Area/Cylinder style 3d list

REDi(Posted 2004) [#1]
Hi all

Could some kind soul please take a look at this piece of code to see where i'm going wrong, Basically its a menu system with each item displayed on a seperate 3d sprite, all of the sprites rotate around a center pivot to give a cylinder effect.
The problem is my CurveAngle() function, I just can't get it to handle the jump from positive to negative angles.
; Use up and down keys to scroll the list

Graphics3D 800,600,32
Const MaxLines = 40
Global SelectedTrackIndex

; create camera
Global Camera = CreateCamera()

; create list wheel
Dim Item(MaxLines)
Dim ItemTex(MaxLines)
Global Wheel = CreatePivot()
PositionEntity Wheel,0,0,4
For n = 1 To MaxLines
	Item(n) = CreateSprite(Wheel)
	ScaleSprite Item(n),2,0.1
	TranslateEntity Item(n),0,0,-1.5,True
	EntityAutoFade Item(n),3.0,3.8	
	EntityBlend Item(n),3
	ItemTex(n) = CreateTexture(512,10)
	TurnEntity Wheel,(360/MaxLines),0,0
Next
UpdateWheelTextures()

Global BackPlate = CreateSprite()
ScaleSprite BackPlate,2,0.1
PositionEntity BackPlate,0,0,3
EntityColor BackPlate,0,0,50


; main loop
While Not KeyDown(1)

	; Scroll up
	If KeyHit(200)
		SelectedTrackIndex = SelectedTrackIndex - 1
		If SelectedTrackIndex < 0 Then SelectedTrackIndex = MaxLines
	EndIf
	
	; Scroll down
	If KeyHit(208)
		SelectedTrackIndex = SelectedTrackIndex + 1
		If SelectedTrackIndex > MaxLines Then SelectedTrackIndex = 0
	EndIf

	UpdateListWheel()

	UpdateWorld()
	RenderWorld()
	Flip

Wend
End



Function UpdateListWheel()

	current# = EntityPitch(Wheel)
	destin#	= (360 / MaxLines) * SelectedTrackIndex

	;dist# = destin# - current#
	;speed# = dist# / 5
	;TurnEntity Wheel,speed#,0,0

	RotateEntity Wheel,CurveAngle(current#,destin#,10),EntityYaw(wheel),EntityRoll(wheel)

End Function

Function UpdateWheelTextures()

	x = TextureWidth(ItemTex(1))/2
	y = TextureHeight(ItemTex(1))/2
	For n=1 To MaxLines
		SetBuffer TextureBuffer(ItemTex(n))
		ClsColor 0,0,0 : Cls
		Color 255,255,255
		Text x,y,"TEST LINE "+n,1,1
		EntityTexture Item(n),ItemTex(n)
	Next
	
End Function

Function CurveAngle#(current#,desired#,smooth#)

	Return current + (desired-current)/smooth

End Function

Thanx for your help!


Floyd(Posted 2004) [#2]
Here's a hastily contrived version which seems to work.

CurveAngle has been fixed.

And Roll is used instead of Pitch.
Pitch has only a 180 degree range, from -90 to +90. Roll has 360 degree range.

; Use up and down keys to scroll the list

Graphics3D 800,600,32
Const MaxLines = 40
Global SelectedTrackIndex

Global current#, destin#  ; not necessary, just for debugging...

; create camera
Global Camera = CreateCamera()

; create list wheel
Dim Item(MaxLines)
Dim ItemTex(MaxLines)
Global Wheel = CreatePivot()
PositionEntity Wheel,0,0,4

TurnEntity wheel, 0, 90, 0 ; point z-axis along original x-axis

For n = 1 To MaxLines
	Item(n) = CreateSprite(Wheel)
	ScaleSprite Item(n),2,0.1
	TranslateEntity Item(n),0,0,-1.5,True
	EntityAutoFade Item(n),3.0,3.8	
	EntityBlend Item(n),3
	ItemTex(n) = CreateTexture(512,10)
	TurnEntity Wheel,0,0,(360/MaxLines)
Next
UpdateWheelTextures()

Global BackPlate = CreateSprite()
ScaleSprite BackPlate,2,0.1
PositionEntity BackPlate,0,0,3
EntityColor BackPlate,0,0,50


; main loop
While Not KeyDown(1)

	; Scroll up
	If KeyHit(200)
		SelectedTrackIndex = SelectedTrackIndex - 1
		If SelectedTrackIndex < 0 Then SelectedTrackIndex = MaxLines
	EndIf
	
	; Scroll down
	If KeyHit(208)
		SelectedTrackIndex = SelectedTrackIndex + 1
		If SelectedTrackIndex > MaxLines Then SelectedTrackIndex = 0
	EndIf

	UpdateListWheel()


	RenderWorld()
	Text 10,10, current
	Text 10,30, destin
	Flip

Wend
End



Function UpdateListWheel()  ; note use of Roll rather than Pitch

	current# = EntityRoll(Wheel)
	destin#	= (360 / MaxLines) * SelectedTrackIndex

; Orient in two steps. This gets rid of confusing interactions 
; among Pitch, Yaw and Roll.

	RotateEntity wheel, 0, 90, 0
	TurnEntity Wheel, 0, 0, CurveAngle(current ,destin ,10)

End Function

Function UpdateWheelTextures()

	x = TextureWidth(ItemTex(1))/2
	y = TextureHeight(ItemTex(1))/2
	For n=1 To MaxLines
		SetBuffer TextureBuffer(ItemTex(n))
		ClsColor 0,0,0 : Cls
		Color 255,255,255
		Text x,y,"TEST LINE "+n,1,1
		EntityTexture Item(n),ItemTex(n)
	Next
	SetBuffer BackBuffer()
	
End Function

Function CurveAngle#(current#,desired#,smooth#)
Local delta#   ;  small version of angle, e.g. +350 becomes -10.

	delta = desired-current
	If Abs(delta) > 180 Then delta = delta - 360 * Sgn(delta)
	Return current + delta/smooth

End Function

This could be neatened up with some effort. But it seems to work.


Rob Farley(Posted 2004) [#3]
For some reason the sprite didn't work squidged up like you had it... however...

Added a bit to rotate the sprite so it's at the right angle on the cylinder... Just replace the initial loopy bit with this.

For n = 1 To MaxLines

	Item(n) = CreateSprite(Wheel)
	ScaleSprite Item(n),2,2
	SpriteViewMode item(n),2
	RotateEntity item(n),(360/maxlines)*(n-1),270,0
	EntityFX item(n),16
	TranslateEntity Item(n),0,0,-1.5,True
	;EntityAutoFade Item(n),3.0,3.8	
	EntityBlend Item(n),3
	ItemTex(n) = CreateTexture(256,256)
	TurnEntity Wheel,0,0,(360/MaxLines)

Next



DJWoodgate(Posted 2004) [#4]
Another possibility. Does not use curveangle at all... (to be honest I could not be bothered to try and figure out how to change it all, so consider this the lazy way).

Function UpdateListWheel()
	
	destin#	= (360 / MaxLines) * (SelectedTrackIndex-1)
	
	vecy#=-Sin(destin) : vecz#=Cos(destin)
		
	AlignToVector wheel,0,vecy,vecz,3,0.1

End Function



A couple of other changes are needed to limit the values correctly...

Global SelectedTrackIndex=1
;....
		If SelectedTrackIndex < 1 Then SelectedTrackIndex = MaxLines
;....
		If SelectedTrackIndex > MaxLines Then SelectedTrackIndex = 1


Well in fact three changes, but who's counting. ;)


REDi(Posted 2004) [#5]
Thanks for all your help guys! :)

I used Davids code in the end, works a treat! Cheers mate :D