Image rotation (like TransformSprite)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Image rotation (like TransformSprite)

Post by Michael Vogel »

Updated the code to get rid of all stripes and holes now - the routines should be a little bit faster as well...
Antialiazing is still not implemented.

Code: Select all

; Define 3D Constants

	Global _Od.f=256
	Global _Vd.f=256
	Global _Oh=256
	Global _Ow=256

	Global Dim ox(_Ow,_Oh)
	Global Dim oy(_Oh)
	Global Dim c(_Ow,_Oh)
	
	#PosX=300
	#PosY=160; 128 should be enough - wrong y-scaling ?!  -h...h = 1 pixel more than 0...h-1
		
; EndDefine

Macro Rad(a)
	(a*#PI/180)
EndMacro
Procedure DrawObject(a)

	Protected _sin.f
	Protected _cos.f
	Protected w=_Ow/2
	Protected h=_Oh/2

	Protected _mx.f
	Protected _my.f
	Protected z.f

	_cos=_Oh/2*Cos(Rad(a))
	_sin=_Oh/2*Sin(Rad(a))

	_Td=_Od+_Vd

	_mx=_Vd*_Td
	_my=_mx*_sin

	For y=-h To h
		z=_Vd*(_Td+_cos*y/h)
		For x=-w To w
			ox(x+w,y+h)=x*_mx/z
		Next x
		oy(y+h)=y*_my/h/z
	Next y

EndProcedure

CreateImage(1, 256, 256)
StartDrawing(ImageOutput(1))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, 256, 256, $FF808080)
For x = 0 To 7
	For y = x&1 To 7 Step 2
		Box(x*32, y*32, 32,32, $FFe0e0e0)
	Next
Next
DrawingMode(#PB_2DDrawing_AlphaBlend)
For i=0 To 33
	Circle(Random(240),Random(240),Random(40),$60000000|Random(#White))
Next i

For x=0 To _Ow-1
	For y=0 To _Oh-1
		c(x,y)=Point(x,y)
	Next y
Next x

For x=0 To _Ow-1
	For y=0 To _Oh-1
		c(x,y)=Point(x,y)
	Next y
Next x

StopDrawing()



OpenWindow(0, 0, 0, 800, 600, "Screen", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0,0,0,800,600)
AddWindowTimer(0,0,20)


Repeat

	Select WaitWindowEvent(25)

	Case #PB_Event_CloseWindow,#WM_CHAR
		End

	Case #PB_Event_Timer
		n+1

		StartDrawing(CanvasOutput(0))
		Box(0,0,500,500,#White)

		;DrawingMode(#PB_2DDrawing_AlphaBlend)
		DrawObject(n*5)
		For y=0 To _Oh-1
			y1=oy(y)+#PosY
			yd=(y1-y2)
			ys=Bool(yd>0)-Bool(yd<0)
			
			If y=0 Or ys
				If ys*yd<>2
					ys=0
				EndIf
				
				For x=0 To _Ow-1
					x1=ox(x,y)+#PosX
					If x And x1>x2+1
						Plot(x2+1,y1,c)
						If ys
							Plot(x2+1,y1-ys,c)
						EndIf
					EndIf
					
					c=$f0000000|c(x,y)
					
					Plot(x1,y1,c)
					If ys
						Plot(x1,y1-ys,c)
					EndIf
					
					x2=x1
				Next x
				
				y2=y1
			EndIf
			
		Next y

		StopDrawing()
	EndSelect
ForEver
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: Image rotation (like TransformSprite)

Post by RASHAD »

Hi MV
Looks very good
Now waiting for supporting any image :)
Thanks for sharing
Egypt my love
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Image rotation (like TransformSprite)

Post by Michael Vogel »

Hi Rashad, you'll have to wait for a long time as I am not an early bird...

...actually I tried to check if using image stripes would do antialiazing for me (otherwise I'd switch to Peek/Poke) - but nor it doesn't look better there are even some white lines in certain cases. It is correct, that the resulting image size (height and width) of the rotated view can be larger than the original dimensions - points nearer to the viewing point seems to 'expand'. But I thought these gap would be filled by enlarging the height of a 'line' by using the difference of the y-positions (variable yd).

However, still a lot of things to do...

Code: Select all

; Define 3D Constants

	Global _Od.f=256
	Global _Vd.f=256
	Global _Oh=200
	Global _Ow=100

	Global _Sx.f
	Global _Sy.f
	Global _Mx
	Global _My

	_Sx=_Ow/(_Vd*_Ow/(_Vd+_Od))
	_Sy=_Oh/(_Vd*_Oh/(_Vd+_Od))
	_Mx=_Vd*_Sx*_Ow/2/(_Vd+_Od-_Oh/2)
	_My=_Oh*1.075; depends on object distance to display (maximum between 65° and 80°)

	Global Dim ox(_Ow,_Oh)
	Global Dim oy(_Oh)
	Global Dim c(_Ow,_Oh)

	#PosX=300
	#PosY=135; 128 should be enough - wrong y-scaling ?!  -h...h = 1 pixel more than 0...h-1

; EndDefine

Macro Rad(a)
	(a*#PI/180)
EndMacro
Procedure DrawObject(a)

	Protected _sin.f
	Protected _cos.f
	Protected w=_Ow/2
	Protected h=_Oh/2

	Protected _mx.f
	Protected _my.f
	Protected z.f

	_cos=_Oh/2*Cos(Rad(a))
	_sin=_Oh/2*Sin(Rad(a))

	_Td=_Od+_Vd

	_mx=_Vd*_Td
	_my=_mx*_sin

	Debug _sx
	Debug _sy
	Debug _mx
	For y=-h To h
		z=_Vd*(_Td+_cos*y/h)
		For x=-w To w
			ox(x+w,y+h)=x*_mx/z
		Next x
		oy(y+h)=y*_my/h/z
	Next y

	Debug oy(0)
	Debug ox(0,0)
	Debug ox(_ow-1,0)

EndProcedure

; Define Image
	If 0
		UsePNGImageDecoder()
		LoadImage(1,"C:\Users\Michael\Desktop\Drawing3D\Image.png")

	Else
		CreateImage(1, 256, 256)
		StartDrawing(ImageOutput(1))
		DrawingMode(#PB_2DDrawing_AllChannels)
		Box(0, 0, 256, 256, $FF808080)
		For x = 0 To 7
			For y = x&1 To 7 Step 2
				Box(x*32, y*32, 32,32, $FFe0e0e0)
			Next
		Next
		DrawingMode(#PB_2DDrawing_AlphaBlend)
		For i=0 To 33
			Circle(Random(240),Random(240),Random(40),$60000000|Random(#White))
		Next i
		
		If 1
			DrawingMode(#PB_2DDrawing_Outlined)
			Box(0,0,_Ow,_Oh,#White)
			Box(1,1,_Ow-2,_Oh-2,#White)
		EndIf
		
		StopDrawing()
	EndIf

	StartDrawing(ImageOutput(1))
	For x=0 To _Ow-1
		For y=0 To _Oh-1
			c(x,y)=Point(x,y)
		Next y
	Next x

	For x=0 To _Ow-1
		For y=0 To _Oh-1
			c(x,y)=Point(x,y)
		Next y
	Next x

	StopDrawing()
; EndDefine

DrawObject(90)
;End

OpenWindow(0, 0, 0, 800, 600, "Screen", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0,0,0,800,600)
AddWindowTimer(0,0,20)



Repeat

	Select WaitWindowEvent(25)

	Case #PB_Event_CloseWindow,#WM_CHAR
		End

	Case #PB_Event_Timer
		n+1

		StartDrawing(CanvasOutput(0))
		Box(0,0,800,600,#White)

		DrawingMode(#PB_2DDrawing_AlphaBlend)
		DrawObject(n*5)

		Debug "> "+Str(n*5)+"° "+Str(oy(0))+" - "+Str(oy(_oH-1))


		For y=0 To _Oh-1
			y1=oy(y)+#PosY
			yd=(y1-y2)
			ys=Bool(yd>0)-Bool(yd<0)

			If y=0 Or ys
				
				If ys*yd<>2
					ys=0
				EndIf
				yd*ys
				
				; Variant I - Pixel by Pixel
				
				For x=0 To _Ow-1
					x1=ox(x,y)+#PosX
					If x And x1>x2+1
						Plot(x2+1,y1,c)
						If ys
							Plot(x2+1,y1-ys,c)
						EndIf
					EndIf

					c=$F0000000|c(x,y)

					Plot(x1,y1,c)
					If ys
						Plot(x1,y1-ys,c)
					EndIf

					x2=x1
				Next x
				
				; Variant II - Drawing the image 
				GrabImage(1,11,0,y,_Ow,1)
				;ResizeImage(11,ox(_Ow-1,y)-ox(0,y),yd+1)
				DrawImage(ImageID(11),600+ox(0,y),y1+100-Bool(ys<0)*yd,ox(_Ow-1,y)-ox(0,y),yd+1)
								
				y2=y1
			EndIf

		Next y

		StopDrawing()
	EndSelect
ForEver
Post Reply