Exemplo n.º 1
0
    public static GlobeMeshData GetGlobeData()
    {
        float uScale = 1.0f;
        float vScale = 1.0f;
        // Make four rows at the polar caps in the place of one
        // to diminish the degenerate triangle issue.
        int   poleVertical    = 3;
        int   uniformVertical = 64;
        int   horizontal      = 128;
        int   vertical        = uniformVertical + poleVertical * 2;
        float radius          = 100.0f;

        int vertexCount = (horizontal + 1) * (vertical + 1);

        VertexAttribs attribs = new VertexAttribs();

        attribs.position = new Vector3[vertexCount];
        attribs.uv0      = new Vector2[vertexCount];
        attribs.color    = new Vector4[vertexCount];

        for (int y = 0; y <= vertical; y++)
        {
            float yf;
            if (y <= poleVertical)
            {
                yf = (float)y / (poleVertical + 1) / uniformVertical;
            }
            else if (y >= vertical - poleVertical)
            {
                yf = (float)(uniformVertical - 1 + ((float)(y - (vertical - poleVertical - 1)) / (poleVertical + 1))) / uniformVertical;
            }
            else
            {
                yf = (float)(y - poleVertical) / uniformVertical;
            }
            float lat    = (yf - 0.5f) * Mathf.PI;
            float cosLat = Mathf.Cos(lat);
            for (int x = 0; x <= horizontal; x++)
            {
                float xf       = (float)x / (float)horizontal;
                float lon      = (0.5f + xf) * Mathf.PI * 2;
                int   curIndex = y * (horizontal + 1) + x;

                if (x == horizontal)
                {
                    // Make sure that the wrap seam is EXACTLY the same
                    // xyz so there is no chance of pixel cracks.
                    attribs.position[curIndex] = attribs.position[y * (horizontal + 1) + 0];
                }
                else
                {
                    var posX = radius * Mathf.Cos(lon) * cosLat;
                    var posY = radius * Mathf.Sin(lon) * cosLat;
                    var posZ = radius * Mathf.Sin(lat);
                    attribs.position[curIndex] = new Vector3(posX, posY, posZ);
                }

                // With a normal mapping, half the triangles degenerate at the poles,
                // which causes seams between every triangle.  It is better to make them
                // a fan, and only get one seam.
                attribs.uv0[curIndex] = new Vector2(y == 0 || y == vertical ? 0.5f : xf * uScale, (1.0f - yf) * vScale);

                attribs.color[curIndex] = new Vector4(1, 1, 1, 1);
            }
        }

        int[] triangleIndices = new int[horizontal * vertical * 6];

        int index = 0;

        for (int x = 0; x < horizontal; x++)
        {
            for (int y = 0; y < vertical; y++)
            {
                triangleIndices[index + 0] = y * (horizontal + 1) + x;
                triangleIndices[index + 1] = y * (horizontal + 1) + x + 1;
                triangleIndices[index + 2] = (y + 1) * (horizontal + 1) + x;
                triangleIndices[index + 3] = (y + 1) * (horizontal + 1) + x;
                triangleIndices[index + 4] = y * (horizontal + 1) + x + 1;
                triangleIndices[index + 5] = (y + 1) * (horizontal + 1) + x + 1;
                index += 6;
            }
        }

        Vector2[] vec2UVs = attribs.uv0;

        for (int i = 0; i < vec2UVs.Length; i++)
        {
            vec2UVs[i] = new Vector2(1.0f - vec2UVs[i].x, vec2UVs[i].y);
        }

        attribs.uv0 = vec2UVs;

        return(new GlobeMeshData(attribs, triangleIndices));
    }
Exemplo n.º 2
0
        public unsafe static NativeMeshSOA Parse(string path, Allocator outputAllocator = Allocator.Persistent, VertexAttribs vertexAttribs = VertexAttribs.Position, VertexOrder vertexOrder = VertexOrder.ByDefinition)
        {
#if VERBOSE
            Debug.LogFormat("trying {0}", path);
#endif

            var text     = File.ReadAllText(path);        //TODO replace with native variant
            var textSize = text.Length;

            // measure the data
            int numPositions = 0;
            int numTexCoords = 0;
            int numNormals   = 0;
            int numFaces     = 0;

            for (int i = 0; i < text.Length; i++)
            {
                if (ReadChar(text, ref i, 'v'))
                {
                    if (ReadBlank(text, ref i))
                    {
                        numPositions++;
                    }
                    else if (ReadChar(text, ref i, 't') && ReadBlank(text, ref i))
                    {
                        numTexCoords++;
                    }
                    else if (ReadChar(text, ref i, 'n') && ReadBlank(text, ref i))
                    {
                        numNormals++;
                    }
                }
                else if (ReadChar(text, ref i, 'f') && ReadBlankGreedy(text, ref i))
                {
                    int readVerts = 0;
                    while (ReadDigit(text, ref i))
                    {
                        ReadUntilNewlineOrBlank(text, ref i);
                        ReadBlankGreedy(text, ref i);
                        readVerts++;
                    }
                    if (readVerts > 2)
                    {
                        numFaces += readVerts - 2;
                    }
                }

                ReadUntilNewline(text, ref i);
            }

#if VERBOSE
            Debug.LogFormat("-- numPositions = {0}", numPositions);
            Debug.LogFormat("-- numTexCoords = {0}", numTexCoords);
            Debug.LogFormat("-- numNormals = {0}", numNormals);
            Debug.LogFormat("-- numFaces = {0}", numFaces);
#endif

            // allocate buffers
            var inputPositions = new NativeArray <Vector3>(numPositions, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var inputTexCoords = new NativeArray <Vector2>(numTexCoords, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var inputNormals   = new NativeArray <Vector3>(numNormals, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var inputFaces     = new NativeArray <InputFace>(numFaces, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            var outputIndicesMax = numFaces * 3;
            var outputIndicesLUT = new NativeHashMap <Hash128, int>(outputIndicesMax, Allocator.Temp);
            var outputPositions  = new NativeArray <Vector3>(outputIndicesMax, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var outputTexCoords  = new NativeArray <Vector2>(outputIndicesMax, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var outputNormals    = new NativeArray <Vector3>(outputIndicesMax, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var outputIndices    = new NativeArray <int>(outputIndicesMax, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            // read the data
            numPositions = 0;
            numTexCoords = 0;
            numNormals   = 0;
            numFaces     = 0;

            for (int i = 0; i < text.Length; i++)
            {
                if (ReadChar(text, ref i, 'v'))
                {
                    if (ReadBlank(text, ref i))
                    {
                        Vector3 position;
                        ReadFloat(text, ref i, out position.x);
                        position.x *= -1.0f;                        //TODO remove this hack
                        ReadBlankGreedy(text, ref i);
                        ReadFloat(text, ref i, out position.y);
                        ReadBlankGreedy(text, ref i);
                        ReadFloat(text, ref i, out position.z);
                        inputPositions[numPositions++] = position;
                    }
                    else if (ReadChar(text, ref i, 't') && ReadBlank(text, ref i))
                    {
                        Vector2 texCoord;
                        ReadFloat(text, ref i, out texCoord.x);
                        ReadBlankGreedy(text, ref i);
                        ReadFloat(text, ref i, out texCoord.y);
                        inputTexCoords[numTexCoords++] = texCoord;
                    }
                    else if (ReadChar(text, ref i, 'n') && ReadBlank(text, ref i))
                    {
                        Vector3 normal;
                        ReadFloat(text, ref i, out normal.x);
                        normal.x *= -1.0f;                        //TODO remove this hack
                        ReadBlankGreedy(text, ref i);
                        ReadFloat(text, ref i, out normal.y);
                        ReadBlankGreedy(text, ref i);
                        ReadFloat(text, ref i, out normal.z);
                        inputNormals[numNormals++] = normal;
                    }
                }
                else if (ReadChar(text, ref i, 'f') && ReadBlankGreedy(text, ref i))
                {
                    InputFace face = new InputFace();
                    if (ReadUInt(text, ref i, out face.v0.idxPosition))
                    {
                        ReadChar(text, ref i, '/');
                        ReadUInt(text, ref i, out face.v0.idxTexCoord);
                        ReadChar(text, ref i, '/');
                        ReadUInt(text, ref i, out face.v0.idxNormal);

                        int readVerts = 1;
                        while (ReadBlankGreedy(text, ref i))
                        {
                            face.v1 = face.v2;
                            if (ReadUInt(text, ref i, out face.v2.idxPosition))
                            {
                                ReadChar(text, ref i, '/');
                                ReadUInt(text, ref i, out face.v2.idxTexCoord);
                                ReadChar(text, ref i, '/');
                                ReadUInt(text, ref i, out face.v2.idxNormal);
                                if (++readVerts > 2)
                                {
                                    inputFaces[numFaces++] = face;
                                }
                            }
                        }
                    }
                }

                ReadUntilNewline(text, ref i);
            }

            // process the data
            int numOutputVertices = 0;
            int numOutputIndices  = 0;

            if (vertexOrder == VertexOrder.ByReference)
            {
                for (int i = 0; i != numFaces; i++)
                {
                    InputFace face = inputFaces[i];

                    var key0 = Hash(in face.v0);
                    var key1 = Hash(in face.v1);
                    var key2 = Hash(in face.v2);
                    int idx0, idx1, idx2;

                    if (outputIndicesLUT.TryGetValue(key0, out idx0) == false)
                    {
                        outputIndicesLUT[key0] = idx0 = numOutputVertices++;
                    }
                    if (outputIndicesLUT.TryGetValue(key1, out idx1) == false)
                    {
                        outputIndicesLUT[key1] = idx1 = numOutputVertices++;
                    }
                    if (outputIndicesLUT.TryGetValue(key2, out idx2) == false)
                    {
                        outputIndicesLUT[key2] = idx2 = numOutputVertices++;
                    }

                    outputPositions[idx0] = inputPositions[(int)face.v0.idxPosition - 1];
                    outputPositions[idx1] = inputPositions[(int)face.v1.idxPosition - 1];
                    outputPositions[idx2] = inputPositions[(int)face.v2.idxPosition - 1];

                    outputTexCoords[idx0] = inputTexCoords[(int)face.v0.idxTexCoord - 1];
                    outputTexCoords[idx1] = inputTexCoords[(int)face.v1.idxTexCoord - 1];
                    outputTexCoords[idx2] = inputTexCoords[(int)face.v2.idxTexCoord - 1];

                    outputNormals[idx0] = inputNormals[(int)face.v0.idxNormal - 1];
                    outputNormals[idx1] = inputNormals[(int)face.v1.idxNormal - 1];
                    outputNormals[idx2] = inputNormals[(int)face.v2.idxNormal - 1];

                    outputIndices[numOutputIndices++] = idx0;
                    outputIndices[numOutputIndices++] = idx1;
                    outputIndices[numOutputIndices++] = idx2;
                }
            }
            else if (vertexOrder == VertexOrder.ByDefinition)
            {
                numOutputVertices = numPositions;

                var indexVisited = new NativeArray <bool>(numPositions, Allocator.Temp, NativeArrayOptions.ClearMemory);

                for (int i = 0; i != numFaces; i++)
                {
                    InputFace face = inputFaces[i];

                    var key0 = Hash(in face.v0);
                    var key1 = Hash(in face.v1);
                    var key2 = Hash(in face.v2);
                    int idx0, idx1, idx2;

                    if (outputIndicesLUT.TryGetValue(key0, out idx0) == false)
                    {
                        if (indexVisited[idx0 = (int)face.v0.idxPosition - 1])
                        {
                            outputIndicesLUT[key0] = idx0 = numOutputVertices++;
                        }
                        else
                        {
                            outputIndicesLUT[key0] = idx0;
                        }
                    }

                    if (outputIndicesLUT.TryGetValue(key1, out idx1) == false)
                    {
                        if (indexVisited[idx1 = (int)face.v1.idxPosition - 1])
                        {
                            outputIndicesLUT[key1] = idx1 = numOutputVertices++;
                        }
                        else
                        {
                            outputIndicesLUT[key1] = idx1;
                        }
                    }

                    if (outputIndicesLUT.TryGetValue(key2, out idx2) == false)
                    {
                        if (indexVisited[idx2 = (int)face.v2.idxPosition - 1])
                        {
                            outputIndicesLUT[key2] = idx2 = numOutputVertices++;
                        }
                        else
                        {
                            outputIndicesLUT[key2] = idx2;
                        }
                    }

                    indexVisited[(int)face.v0.idxPosition - 1] = true;
                    indexVisited[(int)face.v1.idxPosition - 1] = true;
                    indexVisited[(int)face.v2.idxPosition - 1] = true;

                    outputPositions[idx0] = inputPositions[(int)face.v0.idxPosition - 1];
                    outputPositions[idx1] = inputPositions[(int)face.v1.idxPosition - 1];
                    outputPositions[idx2] = inputPositions[(int)face.v2.idxPosition - 1];

                    outputTexCoords[idx0] = inputTexCoords[(int)face.v0.idxTexCoord - 1];
                    outputTexCoords[idx1] = inputTexCoords[(int)face.v1.idxTexCoord - 1];
                    outputTexCoords[idx2] = inputTexCoords[(int)face.v2.idxTexCoord - 1];

                    outputNormals[idx0] = inputNormals[(int)face.v0.idxNormal - 1];
                    outputNormals[idx1] = inputNormals[(int)face.v1.idxNormal - 1];
                    outputNormals[idx2] = inputNormals[(int)face.v2.idxNormal - 1];

                    outputIndices[numOutputIndices++] = idx0;
                    outputIndices[numOutputIndices++] = idx1;
                    outputIndices[numOutputIndices++] = idx2;
                }

                indexVisited.Dispose();
            }

#if VERBOSE
            Debug.LogFormat("output vertex count = {0}", numOutputVertices);
            Debug.LogFormat("output index count = {0}", numOutputIndices);
#endif

            // copy to container
            NativeMeshSOA mesh = new NativeMeshSOA()
            {
                vertexPositions = new NativeArray <Vector3>(numOutputVertices, outputAllocator, NativeArrayOptions.UninitializedMemory),
                vertexTexCoords = new NativeArray <Vector2>(numOutputVertices, outputAllocator, NativeArrayOptions.UninitializedMemory),
                vertexNormals   = new NativeArray <Vector3>(numOutputVertices, outputAllocator, NativeArrayOptions.UninitializedMemory),
                vertexCount     = numOutputVertices,

                faceIndices      = new NativeArray <int>(numOutputIndices, outputAllocator, NativeArrayOptions.UninitializedMemory),
                faceIndicesCount = numOutputIndices,
            };

            NativeArray <Vector3> .Copy(outputPositions, mesh.vertexPositions, numOutputVertices);

            NativeArray <Vector2> .Copy(outputTexCoords, mesh.vertexTexCoords, numOutputVertices);

            NativeArray <Vector3> .Copy(outputNormals, mesh.vertexNormals, numOutputVertices);

            NativeArray <int> .Copy(outputIndices, mesh.faceIndices, numOutputIndices);

            // free buffers
            inputPositions.Dispose();
            inputTexCoords.Dispose();
            inputNormals.Dispose();
            inputFaces.Dispose();

            outputIndicesLUT.Dispose();
            outputPositions.Dispose();
            outputTexCoords.Dispose();
            outputNormals.Dispose();
            outputIndices.Dispose();

            // done
            return(mesh);
        }
Exemplo n.º 3
0
 public GlobeMeshData(VertexAttribs attribs, int[] triangleIndices)
 {
     this.attribs         = attribs;
     this.triangleIndices = triangleIndices;
 }