using System; using UnityEngine; namespace eDriven.Mesh { public class CurvedIllusionPlaneUvGenerator : IUvGenerator { /// /// The curvature parameter controls how much curved will the plane be. /// public float Curvature = 5; /// /// Number of repeat in X direction /// public float UTiles = (float) 1/16; //8; //16f; //16; //(float)1/16; /// /// Number of repeat in Y direction /// public float VTiles = (float) 1/16; //8; //16; //(float)1 / 161; // actual values irrelevant, it's the relation between the sphere's radius and the camera's position which is important // ReSharper disable InconsistentNaming const float SPHERE_RADIUS = 1000; const float CAMERA_DISTANCE = 500; // ReSharper restore InconsistentNaming public Vector2[] CalculateUv(float width, float height, int xVertices, int yVertices) { float xSpace = width / (float)(xVertices-1); float ySpace = height / (float)(yVertices-1); float halfWidth = width / 2; float halfHeight = height / 2; Vector2[] uvs = new Vector2[xVertices * yVertices]; // generate vertex data, imagine a large sphere with the camera located near the top, // the lower the curvature, the larger the sphere. use the angle from the viewer to the // points on the plane // actual values irrelevant, it's the relation between the sphere's radius and the camera's position which is important float sphereRadius = SPHERE_RADIUS - Curvature; float cameraPosition = sphereRadius - CAMERA_DISTANCE; // camera position relative to the sphere center int count = 0; for (int y = 0; y < yVertices; y++) { for (int x = 0; x < xVertices; x++) { // centered on origin Vector3 vec = new Vector3(); vec.x = (x * xSpace) - halfWidth; vec.y = (y * ySpace) - halfHeight; vec.z = 0; Quaternion q = Quaternion.identity; q = Quaternion.Inverse(q); vec = q*vec; vec.Normalize(); // / vec.magnitude; // normalize float sphereDistance = (float)Math.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y; vec.x *= sphereDistance; vec.y *= sphereDistance; // use x and y on sphere as texture coordinates, tiled Vector2 uv = new Vector2(); //uv.x = vec.x*UTiles; //uv.y = vec.y*VTiles; uv.x = vec.x * (0.01f * UTiles); uv.y = 1 - vec.y * (0.01f * VTiles); uvs[count] = uv; count++; } } return uvs; } } }