GetUpVector() public static method

public static GetUpVector ( Quaternion q ) : Vector3
q Quaternion
return Vector3
Beispiel #1
0
    //Create a light mesh object. Cram as much lights as you can into the LightData array. If there are too many lights for one GameObject, it will
    //automatically be split into multiple objects.
    public static GameObject[] CreateLights(string name, LightData[] lightData, Material material)
    {
        int transformAmount = lightData.Length;
        int lightsInThisBatch;

        //The triangle limit is 21844 (65534 vertices) per mesh, so split the objects up if needed.
        int meshAmount = (int)Mathf.Ceil(transformAmount / (float)maxTriangleAmount);

        GameObject[] lightObjects = new GameObject[meshAmount];

        //Get the remainder.
        int remainder = (int)(transformAmount % (float)maxTriangleAmount);

        //Loop through the mesh batches.
        for (int l = 0; l < meshAmount; l++)
        {
            //Get the amount of lights in this mesh batch.
            if (meshAmount == 1)
            {
                lightsInThisBatch = transformAmount;
            }

            else
            {
                //Last mesh batch.
                if (l == (meshAmount - 1))
                {
                    if (remainder == 0)
                    {
                        lightsInThisBatch = maxTriangleAmount;
                    }

                    else
                    {
                        lightsInThisBatch = remainder;
                    }
                }

                else
                {
                    lightsInThisBatch = maxTriangleAmount;
                }
            }

            int vertexCount = lightsInThisBatch * 3;

            Vector4[] corners         = new Vector4[vertexCount];
            Vector2[] uvs             = new Vector2[vertexCount];
            Vector4[] triangleCorners = new Vector4[3];
            Vector2[] triangleUvs     = new Vector2[3];
            bool      directional     = false;
            bool      omnidirectional = false;
            bool      strobe          = false;
            bool      papi            = false;
            Vector3   normal          = Vector3.one;
            Vector3   right           = Vector3.one;
            Vector3   up = Vector3.one;

            //Create temporary arrays.
            Vector3[] centers   = new Vector3[vertexCount];
            Vector3[] normals   = new Vector3[vertexCount];
            int[]     triangles = new int[vertexCount];
            int[]     indices   = new int[vertexCount];

            //What is stored in here, depends on the shader.
            Vector2[] uv3Channel   = new Vector2[vertexCount];
            Vector2[] uv2Channel   = new Vector2[vertexCount];
            Vector2[] uv4Channel   = new Vector2[vertexCount];
            Color[]   colorChannel = new Color[vertexCount];

            if (material.shader.name.Contains("Directional"))
            {
                directional = true;
            }

            if (material.shader.name.Contains("Omnidirectional"))
            {
                omnidirectional = true;
            }

            if (material.shader.name.Contains("Strobe"))
            {
                strobe = true;
            }

            if (material.shader.name.Contains("PAPI"))
            {
                papi = true;
            }

            //Loop through all the lights and set them up.
            for (int i = 0; i < lightsInThisBatch; i++)
            {
                int e     = i * 3;
                int e1    = e + 1;
                int e2    = e + 2;
                int index = (l * maxTriangleAmount) + i;

                //Generate a triangle which fits over a quad.
                GenerateTriangle(out triangleCorners, out triangleUvs, lightData[index].size, Quaternion.identity);

                centers[e]  = lightData[index].position;
                centers[e1] = lightData[index].position;
                centers[e2] = lightData[index].position;

                //Get the rotation vectors.
                normal = -Math3d.GetForwardVector(lightData[index].rotation);
                right  = Math3d.GetRightVector(lightData[index].rotation);
                up     = Math3d.GetUpVector(lightData[index].rotation);

                //Store the scale offset in the w component of the triangle corner.
                triangleCorners[0] = new Vector4(triangleCorners[0].x, triangleCorners[0].y, triangleCorners[0].z, lightData[index].size);
                triangleCorners[1] = new Vector4(triangleCorners[1].x, triangleCorners[1].y, triangleCorners[1].z, lightData[index].size);
                triangleCorners[2] = new Vector4(triangleCorners[2].x, triangleCorners[2].y, triangleCorners[2].z, lightData[index].size);

                corners[e]  = triangleCorners[0];
                corners[e1] = triangleCorners[1];
                corners[e2] = triangleCorners[2];

                uvs[e]  = triangleUvs[0];
                uvs[e1] = triangleUvs[1];
                uvs[e2] = triangleUvs[2];

                normals[e]  = normal;
                normals[e1] = normal;
                normals[e2] = normal;

                if (papi)
                {
                    uv2Channel[e]  = right;
                    uv2Channel[e1] = right;
                    uv2Channel[e2] = right;

                    uv3Channel[e]  = up;
                    uv3Channel[e1] = up;
                    uv3Channel[e2] = up;

                    //Compose the z vector.
                    Vector2 zVector = new Vector2(right.z, up.z);
                    uv4Channel[e]  = zVector;
                    uv4Channel[e1] = zVector;
                    uv4Channel[e2] = zVector;
                }

                if (directional)
                {
                    //Create the back color.
                    Vector2 RG = new Vector2(lightData[index].backColor.r, lightData[index].backColor.g);
                    Vector2 BA = new Vector2(lightData[index].backColor.b, lightData[index].backColor.a);

                    uv2Channel[e]  = RG;
                    uv2Channel[e1] = RG;
                    uv2Channel[e2] = RG;

                    uv3Channel[e]  = BA;
                    uv3Channel[e1] = BA;
                    uv3Channel[e2] = BA;
                }

                if (omnidirectional)
                {
                    //Create the back color.
                    Vector2 RG = new Vector2(lightData[index].backColor.r, lightData[index].backColor.g);

                    uv2Channel[e]  = RG;
                    uv2Channel[e1] = RG;
                    uv2Channel[e2] = RG;

                    uv3Channel[e]  = up;
                    uv3Channel[e1] = up;
                    uv3Channel[e2] = up;

                    //Compose the z vector. The x component is used for the blue component of the back color.
                    Vector2 zVector = new Vector2(lightData[index].backColor.b, up.z);
                    uv4Channel[e]  = zVector;
                    uv4Channel[e1] = zVector;
                    uv4Channel[e2] = zVector;
                }

                if (strobe)
                {
                    //Store the light and group id in the color channel.
                    Color id = new Color(lightData[index].strobeID, lightData[index].strobeGroupID, 0, 0);

                    colorChannel[e]  = id;
                    colorChannel[e1] = id;
                    colorChannel[e2] = id;
                }

                if (directional || omnidirectional)
                {
                    //Create the front color. Note that the light brightness value is stored in the alpha channel.
                    Color frontColor = new Color(lightData[index].frontColor.r, lightData[index].frontColor.g, lightData[index].frontColor.b, lightData[index].brightness);

                    colorChannel[e]  = frontColor;
                    colorChannel[e1] = frontColor;
                    colorChannel[e2] = frontColor;
                }

                triangles[e]  = e;
                triangles[e1] = e1;
                triangles[e2] = e2;

                indices[e]  = e;
                indices[e1] = e1;
                indices[e2] = e2;
            }

            //Create a new gameObject.
            GameObject lightObject = new GameObject(name + " " + l);
            lightObjects[l] = lightObject;

            //Add the required components to the game object.
            MeshFilter   meshFilter   = lightObject.AddComponent <MeshFilter>();
            MeshRenderer meshRenderer = lightObject.AddComponent <MeshRenderer>();

            //Create a new mesh.
            meshFilter.sharedMesh = new Mesh();

            //Apply the mesh properties
            meshFilter.sharedMesh.vertices  = centers;
            meshFilter.sharedMesh.tangents  = corners;            //The mesh corner is stored in the tangent channel. The scale is stored in the w component.
            meshFilter.sharedMesh.normals   = normals;
            meshFilter.sharedMesh.uv        = uvs;
            meshFilter.sharedMesh.triangles = triangles;
            meshFilter.sharedMesh.colors    = colorChannel;     //Front color for directional lights. Alpha is the brightness reduction. //ID for strobe lights.
            meshFilter.sharedMesh.uv2       = uv2Channel;       //RG(BA) back color for directional lights. //Rotation vector for omnidirectional lights and PAPIs.
            meshFilter.sharedMesh.uv3       = uv3Channel;       //(RG)BA back color for directional lights. Alpha is for invisibility. //Rotation vector for omnidirectional lights and PAPIS.
            meshFilter.sharedMesh.uv4       = uv4Channel;       //The UV channels only hold two floats, so use a third UV channel to store the Z components of the vectors.

            //Set the indices.
            meshFilter.sharedMesh.SetIndices(indices, MeshTopology.Triangles, 0);

            //Set the gameObject properties;
            meshRenderer.sharedMaterial       = material;
            meshRenderer.shadowCastingMode    = UnityEngine.Rendering.ShadowCastingMode.Off;
            meshRenderer.receiveShadows       = false;
            meshRenderer.useLightProbes       = false;
            meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
        }

        return(lightObjects);
    }
    //Create a light mesh object. Cram as much lights as you can into the LightData array. If there are too many lights for one GameObject, it will
    //automatically be split into multiple objects.
    //When creating city lights, use the function overload which takes a position array instead of a lightData array.
    private static GameObject[] CreateLightsAll(string name, LightData[] lightData, Vector3[] positions, float simpleShaderLightSize, Material material, UnityEngine.Rendering.IndexFormat meshIndexFormat)
    {
        int transformAmount = 0;

        if (lightData != null)
        {
            transformAmount = lightData.Length;
        }

        else
        {
            transformAmount = positions.Length;
        }

        int lightsInThisBatch;
        int maxTriangles;

        if (meshIndexFormat == UnityEngine.Rendering.IndexFormat.UInt32)
        {
            maxTriangles = maxTriangls32;
        }

        else
        {
            maxTriangles = maxTriangls16;
        }

        //The triangle limit is 21844 (16 bit) or 1431655765 (32 bit) per mesh, so split the objects up if needed.
        int meshAmount = (int)Mathf.Ceil(transformAmount / (float)maxTriangles);

        GameObject[] lightObjects = new GameObject[meshAmount];

        //Get the remainder.
        int remainder = (int)(transformAmount % (float)maxTriangles);

        //Loop through the mesh batches.
        for (int l = 0; l < meshAmount; l++)
        {
            //Get the amount of lights in this mesh batch.
            if (meshAmount == 1)
            {
                lightsInThisBatch = transformAmount;
            }

            else
            {
                //Last mesh batch.
                if (l == (meshAmount - 1))
                {
                    if (remainder == 0)
                    {
                        lightsInThisBatch = maxTriangles;
                    }

                    else
                    {
                        lightsInThisBatch = remainder;
                    }
                }

                else
                {
                    lightsInThisBatch = maxTriangles;
                }
            }

            bool directional     = false;
            bool omnidirectional = false;
            bool strobe          = false;
            bool papi            = false;
            bool simple          = false;

            int vertexCount = lightsInThisBatch * 3;

            Vector4[] corners         = new Vector4[vertexCount];
            Vector2[] uvs             = new Vector2[vertexCount];
            Vector4[] triangleCorners = new Vector4[3];
            Vector2[] triangleUvs     = new Vector2[3];
            Vector3[] normals         = null;

            Vector3 normal = Vector3.one;
            Vector3 right  = Vector3.one;
            Vector3 up     = Vector3.one;

            //Create temporary arrays.
            Vector3[] centers   = new Vector3[vertexCount];
            int[]     triangles = new int[vertexCount];
            int[]     indices   = new int[vertexCount];

            Vector2[] uv2Channel   = null;
            Vector2[] uv3Channel   = null;
            Vector2[] uv4Channel   = null;
            Color[]   colorChannel = null;

            Vector4 corner0 = Vector4.zero;
            Vector4 corner1 = Vector4.zero;
            Vector4 corner2 = Vector4.zero;

            //Generate a triangle which fits over a quad.
            //Taken out of the function for performance.
            //GenerateTriangle(out triangleCorners, out triangleUvs);

            //Set the points, counter clockwise as an upright triangle, with the left
            //corner as point 0, right corner point 1, and top is point 2.
            //X and Y are computed like this:
            //x = (1f / Mathf.Tan(60f * Mathf.Deg2Rad)) + 0.5f;
            //y = // (0.5f / Mathf.Tan(30f * Mathf.Deg2Rad)) + 0.5f;
            triangleCorners[0] = new Vector4(-1.07735f, -0.5f, 0.0f, 1.0f);
            triangleCorners[1] = new Vector4(1.07735f, -0.5f, 0.0f, 1.0f);
            triangleCorners[2] = new Vector4(0.0f, 1.366025f, 0.0f, 1.0f);

            //Computed like this:
            //float u = Math3d.NormalizeComplex(localPoints[i].x, -0.5f, 0.5f);
            //float v = Math3d.NormalizeComplex(localPoints[i].y, -0.5f, 0.5f);
            triangleUvs[0].x = -0.57735f;
            triangleUvs[0].y = 0f;
            triangleUvs[1].x = 1.57735f;
            triangleUvs[1].y = 0f;
            triangleUvs[2].x = 0.5f;
            triangleUvs[2].y = 1.866025f;

            if (lightData != null)
            {
                normals = new Vector3[vertexCount];

                //What is stored in here, depends on the shader.
                uv2Channel   = new Vector2[vertexCount];
                uv3Channel   = new Vector2[vertexCount];
                uv4Channel   = new Vector2[vertexCount];
                colorChannel = new Color[vertexCount];

                if (material.shader.name.Contains("Directional"))
                {
                    directional = true;
                }

                if (material.shader.name.Contains("Omnidirectional"))
                {
                    omnidirectional = true;
                }

                if (material.shader.name.Contains("Strobe"))
                {
                    strobe = true;
                }

                if (material.shader.name.Contains("PAPI"))
                {
                    papi = true;
                }
            }

            else
            {
                simple = true;

                corner0 = new Vector4(triangleCorners[0].x, triangleCorners[0].y, triangleCorners[0].z, simpleShaderLightSize);
                corner1 = new Vector4(triangleCorners[1].x, triangleCorners[1].y, triangleCorners[1].z, simpleShaderLightSize);
                corner2 = new Vector4(triangleCorners[2].x, triangleCorners[2].y, triangleCorners[2].z, simpleShaderLightSize);
            }

            //Loop through all the lights and set them up.
            for (int i = 0; i < lightsInThisBatch; i++)
            {
                float size  = 0;
                int   e     = i * 3;
                int   e1    = e + 1;
                int   e2    = e + 2;
                int   index = (l * maxTriangles) + i;

                if (lightData != null)
                {
                    size = lightData[index].size;

                    centers[e]  = lightData[index].position;
                    centers[e1] = lightData[index].position;
                    centers[e2] = lightData[index].position;

                    corners[e]  = new Vector4(triangleCorners[0].x, triangleCorners[0].y, triangleCorners[0].z, size);
                    corners[e1] = new Vector4(triangleCorners[1].x, triangleCorners[1].y, triangleCorners[1].z, size);
                    corners[e2] = new Vector4(triangleCorners[2].x, triangleCorners[2].y, triangleCorners[2].z, size);
                }

                else
                {
                    size = simpleShaderLightSize;

                    centers[e]  = positions[index];
                    centers[e1] = positions[index];
                    centers[e2] = positions[index];

                    corners[e]  = corner0;
                    corners[e1] = corner1;
                    corners[e2] = corner2;
                }

                uvs[e]  = triangleUvs[0];
                uvs[e1] = triangleUvs[1];
                uvs[e2] = triangleUvs[2];

                if (lightData != null)
                {
                    if (papi || omnidirectional)
                    {
                        up = Math3d.GetUpVector(lightData[index].rotation);
                    }

                    if (!simple)
                    {
                        normal      = -Math3d.GetForwardVector(lightData[index].rotation);
                        normals[e]  = normal;
                        normals[e1] = normal;
                        normals[e2] = normal;
                    }

                    if (papi)
                    {
                        right          = Math3d.GetRightVector(lightData[index].rotation);
                        uv2Channel[e]  = right;
                        uv2Channel[e1] = right;
                        uv2Channel[e2] = right;

                        uv3Channel[e]  = up;
                        uv3Channel[e1] = up;
                        uv3Channel[e2] = up;

                        //Compose the z vector.
                        Vector2 zVector = new Vector2(right.z, up.z);
                        uv4Channel[e]  = zVector;
                        uv4Channel[e1] = zVector;
                        uv4Channel[e2] = zVector;
                    }

                    if (directional)
                    {
                        //Create the back color.
                        Vector2 RG = new Vector2(lightData[index].backColor.r, lightData[index].backColor.g);
                        Vector2 BA = new Vector2(lightData[index].backColor.b, lightData[index].backColor.a);

                        uv2Channel[e]  = RG;
                        uv2Channel[e1] = RG;
                        uv2Channel[e2] = RG;

                        uv3Channel[e]  = BA;
                        uv3Channel[e1] = BA;
                        uv3Channel[e2] = BA;
                    }

                    if (omnidirectional)
                    {
                        //Create the back color.
                        Vector2 RG = new Vector2(lightData[index].backColor.r, lightData[index].backColor.g);

                        uv2Channel[e]  = RG;
                        uv2Channel[e1] = RG;
                        uv2Channel[e2] = RG;

                        uv3Channel[e]  = up;
                        uv3Channel[e1] = up;
                        uv3Channel[e2] = up;

                        //Compose the z vector. The x component is used for the blue component of the back color.
                        Vector2 zVector = new Vector2(lightData[index].backColor.b, up.z);
                        uv4Channel[e]  = zVector;
                        uv4Channel[e1] = zVector;
                        uv4Channel[e2] = zVector;
                    }

                    if (strobe)
                    {
                        //Store the light and group id in the color channel.
                        Color id = new Color(lightData[index].strobeID, lightData[index].strobeGroupID, 0, 0);

                        colorChannel[e]  = id;
                        colorChannel[e1] = id;
                        colorChannel[e2] = id;
                    }

                    if (directional || omnidirectional)
                    {
                        //Create the front color. Note that the light brightness value is stored in the alpha channel.
                        Color frontColor = new Color(lightData[index].frontColor.r, lightData[index].frontColor.g, lightData[index].frontColor.b, lightData[index].brightness);

                        colorChannel[e]  = frontColor;
                        colorChannel[e1] = frontColor;
                        colorChannel[e2] = frontColor;
                    }
                }

                triangles[e]  = e;
                triangles[e1] = e1;
                triangles[e2] = e2;

                indices[e]  = e;
                indices[e1] = e1;
                indices[e2] = e2;
            }

            //Create a new gameObject.
            GameObject lightObject = new GameObject(name + " " + l);
            lightObjects[l] = lightObject;

            //Add the required components to the game object.
            MeshFilter   meshFilter   = lightObject.AddComponent <MeshFilter>();
            MeshRenderer meshRenderer = lightObject.AddComponent <MeshRenderer>();

            //Create a new mesh.
            meshFilter.sharedMesh = new Mesh();

            //Apply the mesh properties.
            meshFilter.sharedMesh.indexFormat = meshIndexFormat;
            meshFilter.sharedMesh.vertices    = centers;
            meshFilter.sharedMesh.tangents    = corners;          //The mesh corner is stored in the tangent channel. The scale is stored in the w component.
            meshFilter.sharedMesh.uv          = uvs;
            meshFilter.sharedMesh.triangles   = triangles;

            if (!simple)
            {
                meshFilter.sharedMesh.normals = normals;
                meshFilter.sharedMesh.colors  = colorChannel;           //Front color for directional lights. Alpha is the brightness reduction. //ID for strobe lights.
                meshFilter.sharedMesh.uv2     = uv2Channel;             //RG(BA) back color for directional lights. //Rotation vector for omnidirectional lights and PAPIs.
                meshFilter.sharedMesh.uv3     = uv3Channel;             //(RG)BA back color for directional lights. Alpha is for invisibility. //Rotation vector for omnidirectional lights and PAPIS.
                meshFilter.sharedMesh.uv4     = uv4Channel;             //The UV channels only hold two floats, so use a third UV channel to store the Z components of the vectors.
            }

            //Set the indices.
            meshFilter.sharedMesh.SetIndices(indices, MeshTopology.Triangles, 0);

            //Set the gameObject properties;
            meshRenderer.sharedMaterial       = material;
            meshRenderer.shadowCastingMode    = UnityEngine.Rendering.ShadowCastingMode.Off;
            meshRenderer.receiveShadows       = false;
            meshRenderer.lightProbeUsage      = UnityEngine.Rendering.LightProbeUsage.Off;
            meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
        }

        return(lightObjects);
    }