Rotation artifacts
BlitzMax Forums/BlitzMax Programming/Rotation artifacts
| ||
I was looking around the forum for some graphic example how to rotate a sprite in different ways, and, I got interested in this strange effect. Look carefully and you see a square pattern appear and disappear over and over again. What is it? How would you make it go away? SuperStrict Type Tentity Field x:Float Field y:Float Field image:TImage Field angle:Float Field x1:Float Field y1:Float Field x2:Float Field y2:Float Field x3:Float Field y3:Float Field x4:Float Field y4:Float Function Create:Tentity(x:Float,y:Float,image:TImage,angle:Float) Local e:Tentity = New Tentity e.x = x e.y = y e.image = image e.angle = angle e.x1:Float = -image.handle_x 'rectangle top left corner e.y1:Float = -image.handle_y e.x2:Float = image.width - image.handle_x 'rectangle top right corner e.y2:Float = -image.handle_y e.x3:Float = image.width - image.handle_x 'rectangle bottom right corner e.y3:Float = image.height - image.handle_y e.x4:Float = -image.handle_x 'rectangle bottom left corner e.y4:Float = image.height - image.handle_y Return e End Function Method collidedpoint:Int(px:Float,py:Float) px = px - x py = py - y Local tx:Float = px*Cos(-angle) - py*Sin(-angle) Local ty:Float = py*Cos(-angle) + px*Sin(-angle) If tx > x1 If ty >y1 If tx < x3 If ty < y3 Return True EndIf EndIf EndIf EndIf Return False End Method Method display() SetRotation angle DrawImage image,x,y Local c:Float = Cos(angle) Local s:Float = Sin(angle) Local px1:Float =x + c*x1 - s*y1 Local py1:Float =y + c*y1 + s*x1 Local px2:Float =x + c*x2 - s*y2 Local py2:Float =y + c*y2 + s*x2 Local px3:Float =x + c*x3 - s*y3 Local py3:Float =y + c*y3 + s*x3 Local px4:Float =x + c*x4 - s*y4 Local py4:Float =y + c*y4 + s*x4 SetRotation 0 DrawOval x-3,y-3,6,6 DrawLine px1,py1,px2,py2 DrawLine px2,py2,px3,py3 DrawLine px3,py3,px4,py4 DrawLine px4,py4,px1,py1 End Method End Type Local img:TImage = CreateImage(256,256) Local pixls:Int Ptr = Int Ptr(LockImage(img).pixels) For Local i:Int = 0 Until img.width*img.height pixls[Rand(img.width*img.height-1)] = $ff00ff00 Next SetImageHandle img,128,0 Graphics 800,600 Local entity:tentity = Tentity.Create(300,300,img,45) Local angle:Float = 0 Repeat Cls() entity.angle = angle If entity.collidedpoint(MouseX(),MouseY()) DrawText "collided",400,300 EndIf entity.display() angle :-.5 Flip() Until KeyDown(key_escape) |
| ||
Looks like a moire pattern.. Trying it on other images and it goes away, so its probably a contrast thing. IE the image your generating is evil ;) The only way i know to lessen this is no filtering or more filtering (like anisotropic). |
| ||
It seems you're right, I need to learn more about this. One thing that amazes me it seem to exist everyhere not only in graphics. Like this fabric.. the moire in it is visible to the naked eye not only to the camera. ![]() I hate filters I hope I can solve it without them. |
| ||
the moire in it is visible to the naked eye not only to the camera. That's because it's a real thing. You are seeing constructive/destructive interference. You see the same thing with the fabric in the picture, or with screens from your windows. If you ever take those outside to wash them you will see such patterns when you place one on top of the other and look through the two layers. It can also happen with a screen and it's own shadow. In your program the interference is between your drawn dots and the grid of screen pixels. Here is an example, a regular pattern of white dots. It is drawn twice with two different orientations. Where the dots land between each other more of the screen is white. SuperStrict Graphics 1024, 1024 Local x:Int, y:Int For x = 0 To 1020 Step 5 For y = 0 To 1020 Step 5 DrawOval x,y, 3,3 Next Next Local dots:TImage = CreateImage( 1024, 1024 ) GrabImage dots, 0, 0 SetImageHandle dots, 512,512 DrawImage dots, 512,512 Flip Delay 1500 Local angle:Float While Not KeyDown( KEY_ESCAPE ) Cls SetRotation 0 DrawImage dots, 512, 512 angle :+ 0.125 If angle > 360.0 Then angle :- 360 SetRotation angle DrawImage dots, 512, 512 Flip Wend |
| ||
I´m just puzzled. The original size was 256x256 so I thought what if you double the size before drawing it and before drawing it (but after rotation), you scale it down equally much? (Here I used a Pixmap at the init to double the size and then for the draw I use a SetScale origsize/biggersize,orgsize/biggersize to restore it). It came close to perfect, so I thought I'd double it even moe or some other size to make the last bit go away. It didn't work at all. Resizing *anything else than a perfect doubling* brought back the pattern with full power (even 513 and all the way to 2047) and it always has equal strength it's not increasing or anything, the effect is either there or it is not. |
| ||
Thanks Floyd for the example, appriciated. Ya I sortof understand the basics behind it, but it's hard to grasp what's actually happening. |
| ||
Hi Casaber. This is a known effect. I managed to create it on the Apple ][ years ago. Here is the equivalent code: Strict Local i Graphics 800,600 For i=0 Until 800 Step 4 DrawLine i,0,799-i,599 If i<600 Then DrawLine 0,i,799,599-i Next Flip WaitKeywhen you have pixels next to each other but not touching, you get unusual effects when you warp them around on a pivot. |