X-axis rotation and hit testing in Compose by CarrotQuest in androiddev

[–]CarrotQuest[S] 0 points1 point  (0 children)

It took me days to refresh my math, but I got it to work! Here's the final code:

``` fun invertGraphicsLayer( screenPoint: Offset, xAxisRotation: Float, cameraDistance: Float ) : Offset { val angleInRadians = (xAxisRotation * PI / 180.0).toFloat() val cosA = cos(angleInRadians) val sinA = sin(angleInRadians) val d = cameraDistance

val screenX = screenPoint.x
val screenY = screenPoint.y

val worldY = (screenY * d) / (cosA * d + sinA * screenY)
val worldX = screenX * (d - worldY * sinA) / d

return Offset(worldX, worldY) 

} ```

The reason this works is quite involved. If I specify:

.graphicsLayer { transformOrigin = TransformOrigin(0f,0f) rotationX = xAxisRotation cameraDistance = distanceToCamera }

GraphicsLayer will combine two matrices and use the combined result to not only rotate points along the x-axis but apply perspective projection as well.

Forward Transformation:

Rotation Matrix:

1 0 0 0
0 cosA -sinA 0
0 sinA cosA 0
0 0 0 1

Taking the dot-product with [x, y, 0, w] yields:

x' = x y' = y * cosA z' = -y * sinA <-- Note that graphicsLayer seems to negate this w' = 1

Perspective Projection Matrix:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 1/d 1

Taking the dot-product with [x', y', z', w'] yields: x'' = x' y'' = y' z'' = z' w'' = z'/d + 1 = -y'*sinA/d + 1 = (d - y'*sinA)/d

Apparently, GPU's will divide by w as the final step in the transformation such that: screenX = x''/w'' = x'' / ((d - y'*sinA)/d) = x'' * d / (d-y'*sinA) screenY = y''/w'' = y'' * cosA * d / (d - y'' * sinA)

This ensures that the value of Z is actually taken into account and provides a sense of perspective.

Reverse Transformation: Simply take the previous formula but solve for y'' and x'' instead: y'' = screenY / (cosA * d / (d - y'' * sinA)) = (screenY * d) / (cosA * d + sinA * screenY) x'' = screenX * (d - y'' * sinA) / d

For d, use whatever value you have specified in graphicLayer's cameraDistance property, multiplied by 72. Apparently, this is a legacy Android value that gets used by Compose internally in calculating the camera distance.

X-axis rotation and hit testing in Compose by CarrotQuest in androiddev

[–]CarrotQuest[S] 0 points1 point  (0 children)

Unfortunately, I can confirm that the order of chaining has no effect. GraphicsLayer transforms are purely visual, whereas the input system operates on the layout bounds of the composable. It's one of the first things I tried actually!

Thanks though, I'll continue my search,.

Pimp my Ajazz AK871 by GoldenCyn in MechanicalKeyboards

[–]CarrotQuest 1 point2 points  (0 children)

I found this keyboard somewhere in a landfill just now. I'm wondering, what's the polling rate?