Exemplo n.º 1
0
        /**
         * Convert the normals back to cartesian coordinates.
         */
        private float[] restoreNormals(int[] intNormals, float[] vertices, int[] indices, float normalPrecision)
        {
            // Calculate smooth normals (nominal normals)
            float[] smoothNormals = CommonAlgorithm.calcSmoothNormals(vertices, indices);
            float[] normals       = new float[vertices.Length];

            int vc = vertices.Length / Mesh.CTM_POSITION_ELEMENT_COUNT;
            int ne = Mesh.CTM_NORMAL_ELEMENT_COUNT;

            for (int i = 0; i < vc; ++i)
            {
                // Get the normal magnitude from the first of the three normal elements
                float magn = intNormals[i * ne] * normalPrecision;

                // Get phi and theta (spherical coordinates, relative to the smooth normal).
                double thetaScale, theta;
                int    intPhi = intNormals[i * ne + 1];
                double phi    = intPhi * (0.5 * Math.PI) * normalPrecision;
                if (intPhi == 0)
                {
                    thetaScale = 0.0f;
                }
                else if (intPhi <= 4)
                {
                    thetaScale = Math.PI / 2.0f;
                }
                else
                {
                    thetaScale = (2.0f * Math.PI) / intPhi;
                }
                theta = intNormals[i * ne + 2] * thetaScale - Math.PI;

                // Convert the normal from the angular representation (phi, theta) back to
                // cartesian coordinates
                double[] n2 = new double[3];
                n2[0] = Math.Sin(phi) * Math.Cos(theta);
                n2[1] = Math.Sin(phi) * Math.Sin(theta);
                n2[2] = Math.Cos(phi);
                float[]  basisAxes = CommonAlgorithm.makeNormalCoordSys(smoothNormals, i * ne);
                double[] n         = new double[3];
                for (int j = 0; j < 3; ++j)
                {
                    n[j] = basisAxes[j] * n2[0]
                           + basisAxes[3 + j] * n2[1]
                           + basisAxes[6 + j] * n2[2];
                }

                // Apply normal magnitude, and output to the normals array
                for (int j = 0; j < 3; ++j)
                {
                    normals[i * ne + j] = (float)(n[j] * magn);
                }
            }

            return(normals);
        }
Exemplo n.º 2
0
        /**
         * Convert the normals to a new coordinate system: magnitude, phi, theta
         * (relative to predicted smooth normals).
         */
        private int[] makeNormalDeltas(float[] vertices, float[] normals, int[] indices, SortableVertex[] sortVertices)
        {
            // Calculate smooth normals (Note: aVertices and aIndices use the sorted
            // index space, so smoothNormals will too)
            float[] smoothNormals = CommonAlgorithm.calcSmoothNormals(vertices, indices);

            // Normal scaling factor
            float scale = 1.0f / normalPrecision;

            int vc = vertices.Length / Mesh.CTM_POSITION_ELEMENT_COUNT;

            int[] intNormals = new int[vc * Mesh.CTM_NORMAL_ELEMENT_COUNT];
            for (int i = 0; i < vc; ++i)
            {
                // Get old normal index (before vertex sorting)
                int oldIdx = sortVertices [i].originalIndex;

                // Calculate normal magnitude (should always be 1.0 for unit length normals)
                float magn = (float)Math.Sqrt(normals [oldIdx * 3] * normals [oldIdx * 3]
                                              + normals [oldIdx * 3 + 1] * normals [oldIdx * 3 + 1]
                                              + normals [oldIdx * 3 + 2] * normals [oldIdx * 3 + 2]);
                if (magn < 1e-10f)
                {
                    magn = 1.0f;
                }

                // Invert magnitude if the normal is negative compared to the predicted
                // smooth normal
                if ((smoothNormals [i * 3] * normals [oldIdx * 3]
                     + smoothNormals [i * 3 + 1] * normals [oldIdx * 3 + 1]
                     + smoothNormals [i * 3 + 2] * normals [oldIdx * 3 + 2]) < 0.0f)
                {
                    magn = -magn;
                }

                // Store the magnitude in the first element of the three normal elements
                intNormals [i * 3] = (int)Math.Floor(scale * magn + 0.5f);

                // Normalize the normal (1 / magn) - and flip it if magn < 0
                magn = 1.0f / magn;
                float[] n = new float[3];
                for (int j = 0; j < 3; ++j)
                {
                    n [j] = normals [oldIdx * 3 + j] * magn;
                }

                // Convert the normal to angular representation (phi, theta) in a coordinate
                // system where the nominal (smooth) normal is the Z-axis
                float[] basisAxes = CommonAlgorithm.makeNormalCoordSys(smoothNormals, i * 3);
                float[] n2        = new float[3];
                for (int j = 0; j < 3; ++j)
                {
                    n2 [j] = basisAxes [j * 3] * n [0]
                             + basisAxes [j * 3 + 1] * n [1]
                             + basisAxes [j * 3 + 2] * n [2];
                }
                double phi, theta, thetaScale;
                if (n2 [2] >= 1.0f)
                {
                    phi = 0.0f;
                }
                else
                {
                    phi = Math.Acos(n2 [2]);
                }
                theta = Math.Atan2(n2 [1], n2 [0]);

                // Round phi and theta (spherical coordinates) to integers. Note: We let the
                // theta resolution vary with the x/y circumference (roughly phi).
                int intPhi = (int)Math.Floor(phi * (scale / (0.5 * Math.PI)) + 0.5);
                if (intPhi == 0)
                {
                    thetaScale = 0.0;
                }
                else if (intPhi <= 4)
                {
                    thetaScale = 2.0 / Math.PI;
                }
                else
                {
                    thetaScale = intPhi / (2.0 * Math.PI);
                }
                intNormals [i * 3 + 1] = intPhi;
                intNormals [i * 3 + 2] = (int)Math.Floor((theta + Math.PI) * thetaScale + 0.5f);
            }
            return(intNormals);
        }