private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength) { Vector3 vec; Vector3 norm; float sphereDistance; unsafe { // lock the vertex buffer IntPtr data = vertexBuffer.Lock(BufferLocking.Discard); float* pData = (float*)data.ToPointer(); for (int y = 0; y < ySegments + 1; ++y) { for (int x = 0; x < xSegments + 1; ++x) { // centered on origin vec.x = (x * xSpace) - halfWidth; vec.y = (y * ySpace) - halfHeight; vec.z = 0.0f; // transform by orientation and distance vec = xform * vec; // assign to geometry *pData++ = vec.x; *pData++ = vec.y; *pData++ = vec.z; // build bounds as we go if (firstTime) { min = vec; max = vec; maxSquaredLength = vec.LengthSquared; firstTime = false; } else { min.Floor(vec); max.Ceil(vec); maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared); } if (normals) { norm = Vector3.UnitZ; norm = orientation * norm; *pData++ = vec.x; *pData++ = vec.y; *pData++ = vec.z; } // generate texture coordinates, normalize position, modify by orientation to return +y up vec = orientation.Inverse() * vec; vec.Normalize(); // find distance to sphere sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y; vec.x *= sphereDistance; vec.z *= sphereDistance; // use x and y on sphere as texture coordinates, tiled float s = vec.x * (0.01f * uTiles); float t = vec.z * (0.01f * vTiles); for (int i = 0; i < numberOfTexCoordSets; i++) { *pData++ = s; *pData++ = (1 - t); } } // x } // y // unlock the buffer vertexBuffer.Unlock(); } // unsafe }
/// <summary> /// Internal method for building an inverse Matrix4 from orientation / scale / position. /// </summary> /// <remarks> /// As makeTransform except it build the inverse given the same data as makeTransform, so /// performing -translation, 1/scale, -rotate in that order. /// </remarks> /// <param name="position"></param> /// <param name="scale"></param> /// <param name="orientation"></param> /// <returns></returns> protected void MakeInverseTransform(Vector3 position, Vector3 scale, Quaternion orientation, ref Matrix4 destMatrix) { destMatrix = Matrix4.Identity; // Invert the parameters Vector3 invTranslate = -position; Vector3 invScale = Vector3.Zero; invScale.x = 1.0f / scale.x; invScale.y = 1.0f / scale.y; invScale.z = 1.0f / scale.z; Quaternion invRot = orientation.Inverse(); // Because we're inverting, order is translation, rotation, scale // So make translation relative to scale & rotation invTranslate.x *= invScale.x; // scale invTranslate.y *= invScale.y; // scale invTranslate.z *= invScale.z; // scale invTranslate = invRot * invTranslate; // rotate // Next, make a 3x3 rotation matrix and apply inverse scale Matrix3 rot3x3 = invRot.ToRotationMatrix(); Matrix3 scale3x3= Matrix3.Zero; scale3x3.m00 = invScale.x; scale3x3.m11 = invScale.y; scale3x3.m22 = invScale.z; // Set up final matrix with scale & rotation destMatrix = scale3x3 * rot3x3; destMatrix.Translation = invTranslate; }