using System.Collections.Generic; using UnityEngine; using UnityEngine.Diagnostics; namespace SplashEdit.RuntimeCode { /// /// Represents a vertex formatted for the PSX (PlayStation) style rendering. /// public struct PSXVertex { // Position components in fixed-point format. public short vx, vy, vz; // Normal vector components in fixed-point format. public short nx, ny, nz; // Texture coordinates. public byte u, v; // Vertex color components. public byte r, g, b; } /// /// Represents a triangle defined by three PSX vertices. /// public struct Tri { public PSXVertex v0; public PSXVertex v1; public PSXVertex v2; } /// /// A mesh structure that holds a list of triangles converted from a Unity mesh into the PSX format. /// [System.Serializable] public class PSXMesh { public List Triangles; /// /// Creates a PSXMesh from a Unity Mesh by converting its vertices, normals, UVs, and applying shading. /// /// The Unity mesh to convert. /// Width of the texture (default is 256). /// Height of the texture (default is 256). /// Optional transform to convert vertices to world space. /// A new PSXMesh containing the converted triangles. public static PSXMesh CreateFromUnityMesh(Mesh mesh, float GTEScaling, int textureWidth = 256, int textureHeight = 256, Transform transform = null) { PSXMesh psxMesh = new PSXMesh { Triangles = new List() }; // Get mesh data arrays. Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; Vector2[] uv = mesh.uv; int[] indices = mesh.triangles; // Determine the primary light's direction and color for shading. Light mainLight = RenderSettings.sun; Vector3 lightDir = mainLight ? mainLight.transform.forward : Vector3.down; // Fixed: Removed negation. Color lightColor = mainLight ? mainLight.color * mainLight.intensity : Color.white; // Iterate over each triangle (group of 3 indices). for (int i = 0; i < indices.Length; i += 3) { int vid0 = indices[i]; int vid1 = indices[i + 1]; int vid2 = indices[i + 2]; // Transform vertices to world space if a transform is provided. Vector3 v0 = transform ? transform.TransformPoint(vertices[vid0]) : vertices[vid0]; Vector3 v1 = transform ? transform.TransformPoint(vertices[vid1]) : vertices[vid1]; Vector3 v2 = transform ? transform.TransformPoint(vertices[vid2]) : vertices[vid2]; // Convert vertices to PSX format including fixed-point conversion and shading. PSXVertex psxV0 = ConvertToPSXVertex(v0, GTEScaling, normals[vid0], uv[vid0], lightDir, lightColor, textureWidth, textureHeight); PSXVertex psxV1 = ConvertToPSXVertex(v1, GTEScaling, normals[vid1], uv[vid1], lightDir, lightColor, textureWidth, textureHeight); PSXVertex psxV2 = ConvertToPSXVertex(v2, GTEScaling, normals[vid2], uv[vid2], lightDir, lightColor, textureWidth, textureHeight); // Add the constructed triangle to the mesh. psxMesh.Triangles.Add(new Tri { v0 = psxV0, v1 = psxV1, v2 = psxV2 }); } return psxMesh; } /// /// Converts a Unity vertex into a PSXVertex by applying fixed-point conversion, shading, and UV mapping. /// /// The position of the vertex. /// The normal vector at the vertex. /// Texture coordinates for the vertex. /// The light direction used for shading calculations. /// The color of the light affecting the vertex. /// Width of the texture for UV scaling. /// Height of the texture for UV scaling. /// A PSXVertex with converted coordinates, normals, UVs, and color. private static PSXVertex ConvertToPSXVertex(Vector3 vertex, float GTEScaling, Vector3 normal, Vector2 uv, Vector3 lightDir, Color lightColor, int textureWidth, int textureHeight) { // Calculate light intensity based on the angle between the normalized normal and light direction. float lightIntensity = Mathf.Clamp01(Vector3.Dot(normal.normalized, lightDir)); // Compute the final shaded color by multiplying the light color by the intensity. Color shadedColor = lightColor * lightIntensity; PSXVertex psxVertex = new PSXVertex { // Convert position to fixed-point, clamping values to a defined range. vx = (short)PSXTrig.ConvertCoordinateToPSX(vertex.x, GTEScaling), vy = (short)PSXTrig.ConvertCoordinateToPSX(-vertex.y, GTEScaling), vz = (short)PSXTrig.ConvertCoordinateToPSX(vertex.z, GTEScaling), // Convert normals to fixed-point. nx = (short)PSXTrig.ConvertCoordinateToPSX(normal.x), ny = (short)PSXTrig.ConvertCoordinateToPSX(-normal.y), nz = (short)PSXTrig.ConvertCoordinateToPSX(normal.z), // Map UV coordinates to a byte range after scaling based on texture dimensions. u = (byte)(Mathf.Clamp((uv.x * (textureWidth - 1)), 0, 255)), v = (byte)(Mathf.Clamp(((1.0f - uv.y) * (textureHeight - 1)), 0, 255)), // Convert the computed color to a byte range. r = (byte)(Mathf.Clamp(shadedColor.r * 255, 0, 255)), g = (byte)(Mathf.Clamp(shadedColor.g * 255, 0, 255)), b = (byte)(Mathf.Clamp(shadedColor.b * 255, 0, 255)) }; return psxVertex; } } }