/// <summary>
    /// Call this function to create geometry handle
    /// </summary>
    void CreatePropagationGeometry()
    {
        AudioConfiguration config = AudioSettings.GetConfiguration();

        // Create Geometry
        if (PropIFace.CreateAudioGeometry(out geometryHandle) != OSPSuccess)
        {
            throw new Exception("Unable to create geometry handle");
        }

        // Upload Mesh
        if (filePath != null && filePath.Length != 0 && fileEnabled && Application.isPlaying)
        {
            if (!ReadFile())
            {
                Debug.Log("Failed to read file, attempting to regenerate audio geometry");

                // We should not try to upload data dynamically if data already exists
                UploadGeometry();
            }
        }
        else
        {
            UploadGeometry();
        }
    }
Exemple #2
0
    //***********************************************************************
    // Upload

    public void UploadMaterial()
    {
        if (materialHandle == IntPtr.Zero)
        {
            return;
        }

        // Absorption
        PropIFace.AudioMaterialReset(materialHandle, MaterialProperty.ABSORPTION);

        foreach (Point p in absorption.points)
        {
            PropIFace.AudioMaterialSetFrequency(materialHandle, MaterialProperty.ABSORPTION,
                                                p.frequency, p.data);
        }

        // Transmission
        PropIFace.AudioMaterialReset(materialHandle, MaterialProperty.TRANSMISSION);

        foreach (Point p in transmission.points)
        {
            PropIFace.AudioMaterialSetFrequency(materialHandle, MaterialProperty.TRANSMISSION,
                                                p.frequency, p.data);
        }

        // Scattering
        PropIFace.AudioMaterialReset(materialHandle, MaterialProperty.SCATTERING);

        foreach (Point p in scattering.points)
        {
            PropIFace.AudioMaterialSetFrequency(materialHandle, MaterialProperty.SCATTERING,
                                                p.frequency, p.data);
        }
    }
Exemple #3
0
 public void DestroyInternal()
 {
     if (materialHandle != IntPtr.Zero)
     {
         // Destroy the material.
         PropIFace.DestroyAudioMaterial(materialHandle);
         materialHandle = IntPtr.Zero;
     }
 }
    /// <summary>
    /// Call when destroyed
    /// </summary>
    private void OnDestroy()
    {
        // DESTROY GEOMETRY
        if (geometryHandle != IntPtr.Zero && PropIFace.DestroyAudioGeometry(geometryHandle) != OSPSuccess)
        {
            throw new Exception("Unable to destroy geometry");
        }

        geometryHandle = IntPtr.Zero;
    }
    //***********************************************************************
    // ReadFile - Read the serialized mesh file.

    public bool ReadFile()
    {
        if (filePath == null || filePath.Length == 0)
        {
            Debug.Log("Invalid mesh file path");
            return(false);
        }

        if (PropIFace.AudioGeometryReadMeshFile(geometryHandle, filePath) != OSPSuccess)
        {
            Debug.Log("Error reading mesh file " + filePath);
            return(false);
        }

        return(true);
    }
Exemple #6
0
    public void StartInternal()
    {
        // Ensure that the material is not initialized twice.
        if (materialHandle != IntPtr.Zero)
        {
            return;
        }

        // Create the internal material.
        if (PropIFace.CreateAudioMaterial(out materialHandle) != ONSPPropagationGeometry.OSPSuccess)
        {
            throw new Exception("Unable to create internal audio material");
        }

        // Run the updates to initialize the material.
        UploadMaterial();
    }
    /// <summary>
    /// Update the world transform (TODO)
    /// </summary>
    private void Update()
    {
        if (geometryHandle == IntPtr.Zero)
        {
            return;
        }

        Matrix4x4 m = transform.localToWorldMatrix;

        // Note: flip Z to convert from left-handed (+Z forward) to right-handed (+Z backward)
        float[] matrix = { m[0, 0], m[1, 0], -m[2, 0], m[3, 0],
                           m[0, 1], m[1, 1], -m[2, 1], m[3, 1],
                           m[0, 2], m[1, 2], -m[2, 2], m[3, 2],
                           m[0, 3], m[1, 3], -m[2, 3], m[3, 3] };

        PropIFace.AudioGeometrySetTransform(geometryHandle, matrix);
    }
    //***********************************************************************
    // WriteFile - Write the serialized mesh file.

    public bool WriteFile()
    {
        if (filePath == null || filePath.Length == 0)
        {
            Debug.Log("Invalid mesh file path");
            return(false);
        }

        AudioConfiguration config = AudioSettings.GetConfiguration();

        // Create a temporary geometry.
        IntPtr tempGeometryHandle = IntPtr.Zero;

        if (PropIFace.CreateAudioGeometry(out tempGeometryHandle) != OSPSuccess)
        {
            throw new Exception("Unable to create temp geometry handle");
        }

        // Upload the mesh geometry.
        if (uploadMesh(tempGeometryHandle, gameObject, gameObject.transform.worldToLocalMatrix, false) != OSPSuccess)
        {
            Debug.Log("Error uploading mesh " + gameObject.name);
            return(false);
        }

        // Write the mesh to a file.
        if (PropIFace.AudioGeometryWriteMeshFile(tempGeometryHandle, filePath) != OSPSuccess)
        {
            Debug.Log("Error writing mesh file " + filePath);
            return(false);
        }

        // Destroy the geometry.
        PropIFace.DestroyAudioGeometry(tempGeometryHandle);

        Debug.Log("Write mesh file " + filePath);
        return(true);
    }
    //
    // CALL THIS ON GAME OBJECT THAT HAS GEOMETRY ATTACHED TO IT
    //
    private int uploadMesh(IntPtr geometryHandle, GameObject meshObject, Matrix4x4 worldToLocal, bool ignoreStatic)
    {
        // Get the child mesh objects.
        List <MeshMaterial>    meshes   = new List <MeshMaterial>();
        List <TerrainMaterial> terrains = new List <TerrainMaterial>();

        traverseMeshHierarchy(meshObject, null, includeChildMeshes, meshes, terrains, ignoreStatic);

        //***********************************************************************
        // Count the number of vertices and indices.

        int  totalVertexCount   = 0;
        uint totalIndexCount    = 0;
        int  totalFaceCount     = 0;
        int  totalMaterialCount = 0;

        foreach (MeshMaterial m in meshes)
        {
            Mesh mesh = m.meshFilter.sharedMesh;

            totalMaterialCount += mesh.subMeshCount;
            totalVertexCount   += mesh.vertexCount;

            for (int i = 0; i < mesh.subMeshCount; i++)
            {
                MeshTopology topology = mesh.GetTopology(i);
                if (topology == MeshTopology.Triangles || topology == MeshTopology.Quads)
                {
                    uint meshIndexCount = mesh.GetIndexCount(i);
                    totalIndexCount += meshIndexCount;

                    if (topology == MeshTopology.Triangles)
                    {
                        totalFaceCount += (int)meshIndexCount / 3;
                    }
                    else if (topology == MeshTopology.Quads)
                    {
                        totalFaceCount += (int)meshIndexCount / 4;
                    }
                }
            }
        }

        foreach (TerrainMaterial t in terrains)
        {
            TerrainData terrain = t.terrain.terrainData;

            int w           = terrain.heightmapWidth;
            int h           = terrain.heightmapHeight;
            int wRes        = (w - 1) / terrainDecimation + 1;
            int hRes        = (h - 1) / terrainDecimation + 1;
            int vertexCount = wRes * hRes;
            int indexCount  = (wRes - 1) * (hRes - 1) * 6;

            totalMaterialCount++;
            totalVertexCount += vertexCount;
            totalIndexCount  += (uint)indexCount;
            totalFaceCount   += indexCount / 3;
        }

        //***********************************************************************
        // Copy the mesh data.

        List <Vector3> tempVertices = new List <Vector3>();
        List <int>     tempIndices  = new List <int>();

        MeshGroup[] groups   = new MeshGroup[totalMaterialCount];
        float[]     vertices = new float[totalVertexCount * 3];
        int[]       indices  = new int[totalIndexCount];

        int vertexOffset = 0;
        int indexOffset  = 0;
        int groupOffset  = 0;

        foreach (MeshMaterial m in meshes)
        {
            MeshFilter meshFilter = m.meshFilter;
            Mesh       mesh       = meshFilter.sharedMesh;

            // Compute the combined transform to go from mesh-local to geometry-local space.
            Matrix4x4 matrix = worldToLocal * meshFilter.gameObject.transform.localToWorldMatrix;

            // Get the mesh vertices.
            tempVertices.Clear();
            mesh.GetVertices(tempVertices);

            // Copy the Vector3 vertices into a packed array of floats for the API.
            int meshVertexCount = tempVertices.Count;
            for (int i = 0; i < meshVertexCount; i++)
            {
                // Transform into the parent space.
                Vector3 v      = matrix.MultiplyPoint3x4(tempVertices[i]);
                int     offset = (vertexOffset + i) * 3;
                vertices[offset + 0] = v.x;
                vertices[offset + 1] = v.y;
                vertices[offset + 2] = v.z;
            }

            // Copy the data for each submesh.
            for (int i = 0; i < mesh.subMeshCount; i++)
            {
                MeshTopology topology = mesh.GetTopology(i);

                if (topology == MeshTopology.Triangles || topology == MeshTopology.Quads)
                {
                    // Get the submesh indices.
                    tempIndices.Clear();
                    mesh.GetIndices(tempIndices, i);
                    int subMeshIndexCount = tempIndices.Count;

                    // Copy and adjust the indices.
                    for (int j = 0; j < subMeshIndexCount; j++)
                    {
                        indices[indexOffset + j] = tempIndices[j] + vertexOffset;
                    }

                    // Initialize the group.
                    if (topology == MeshTopology.Triangles)
                    {
                        groups[groupOffset + i].faceType  = FaceType.TRIANGLES;
                        groups[groupOffset + i].faceCount = (UIntPtr)(subMeshIndexCount / 3);
                    }
                    else if (topology == MeshTopology.Quads)
                    {
                        groups[groupOffset + i].faceType  = FaceType.QUADS;
                        groups[groupOffset + i].faceCount = (UIntPtr)(subMeshIndexCount / 4);
                    }

                    groups[groupOffset + i].indexOffset = (UIntPtr)indexOffset;

                    if (m.materials != null && m.materials.Length != 0)
                    {
                        int matIndex = i;
                        if (matIndex >= m.materials.Length)
                        {
                            matIndex = m.materials.Length - 1;
                        }
                        m.materials[matIndex].StartInternal();
                        groups[groupOffset + i].material = m.materials[matIndex].materialHandle;
                    }
                    else
                    {
                        groups[groupOffset + i].material = IntPtr.Zero;
                    }

                    indexOffset += subMeshIndexCount;
                }
            }

            vertexOffset += meshVertexCount;
            groupOffset  += mesh.subMeshCount;
        }

        foreach (TerrainMaterial t in terrains)
        {
            TerrainData terrain = t.terrain.terrainData;

            // Compute the combined transform to go from mesh-local to geometry-local space.
            Matrix4x4 matrix = worldToLocal * t.terrain.gameObject.transform.localToWorldMatrix;

            int w = terrain.heightmapWidth;
            int h = terrain.heightmapHeight;
            float[,] tData = terrain.GetHeights(0, 0, w, h);

            Vector3 meshScale = terrain.size;
            meshScale = new Vector3(meshScale.x / (w - 1) * terrainDecimation, meshScale.y, meshScale.z / (h - 1) * terrainDecimation);
            int wRes          = (w - 1) / terrainDecimation + 1;
            int hRes          = (h - 1) / terrainDecimation + 1;
            int vertexCount   = wRes * hRes;
            int triangleCount = (wRes - 1) * (hRes - 1) * 2;

            // Initialize the group.
            groups[groupOffset].faceType    = FaceType.TRIANGLES;
            groups[groupOffset].faceCount   = (UIntPtr)triangleCount;
            groups[groupOffset].indexOffset = (UIntPtr)indexOffset;

            if (t.materials != null && 0 < t.materials.Length)
            {
                t.materials[0].StartInternal();
                groups[groupOffset].material = t.materials[0].materialHandle;
            }
            else
            {
                groups[groupOffset].material = IntPtr.Zero;
            }

            // Build vertices and UVs
            for (int y = 0; y < hRes; y++)
            {
                for (int x = 0; x < wRes; x++)
                {
                    int     offset = (vertexOffset + y * wRes + x) * 3;
                    Vector3 v      = matrix.MultiplyPoint3x4(Vector3.Scale(meshScale, new Vector3(y, tData[x * terrainDecimation, y * terrainDecimation], x)));
                    vertices[offset + 0] = v.x;
                    vertices[offset + 1] = v.y;
                    vertices[offset + 2] = v.z;
                }
            }

            // Build triangle indices: 3 indices into vertex array for each triangle
            for (int y = 0; y < hRes - 1; y++)
            {
                for (int x = 0; x < wRes - 1; x++)
                {
                    // For each grid cell output two triangles
                    indices[indexOffset + 0] = (vertexOffset + (y * wRes) + x);
                    indices[indexOffset + 1] = (vertexOffset + ((y + 1) * wRes) + x);
                    indices[indexOffset + 2] = (vertexOffset + (y * wRes) + x + 1);

                    indices[indexOffset + 3] = (vertexOffset + ((y + 1) * wRes) + x);
                    indices[indexOffset + 4] = (vertexOffset + ((y + 1) * wRes) + x + 1);
                    indices[indexOffset + 5] = (vertexOffset + (y * wRes) + x + 1);
                    indexOffset += 6;
                }
            }

            vertexOffset += vertexCount;
            groupOffset++;
        }

        // Upload mesh data
        return(PropIFace.AudioGeometryUploadMeshArrays(geometryHandle,
                                                       vertices, totalVertexCount,
                                                       indices, indices.Length,
                                                       groups, groups.Length));
    }