public IEnumerator ImportFaceMeshData(MeshDataContainer data)
    {
        yield return(new WaitForEndOfFrame());

        int totalFrames = data.meshDataList.Count;
        int totalInputs = data.meshDataList[25].pos.Count;
        //int totalInputs = data.meshDataList[25].pos.Length;
        int maxValue = 1;

        for (int graph = 0; graph < totalInputs; graph++)
        {
            List <Vector2> GraphData = new List <Vector2>();
            for (int frame = 0; frame < data.meshDataList.Count; frame++)
            {
                Vector3 tmp = new Vector3((float)data.meshDataList[frame].pos[graph].x, (float)data.meshDataList[frame].pos[graph].y, (float)data.meshDataList[frame].pos[graph].z);
                float   mag = tmp.sqrMagnitude * 100;

                var offsetFrame  = (int)(frame - (totalFrames / 2));
                var offsetVector = mag - (0.65f);
                GraphData.Add(new Vector2(offsetFrame, offsetVector));
            }


            LineRendererHUD lineRenderer = GenerateGraph();
            lineRenderer.points    = GraphData;
            lineRenderer.thickness = 5;
            //grid size = x = frame amout, y max value
            lineRenderer.gridSize = new Vector2Int(totalFrames, maxValue);
            lineRenderer.color    = new Color(1, 0, 0, 0.15f);
        }
    }
Example #2
0
        /// <summary>
        /// Builds the navigation graph for obstacle.
        /// If updateObstc is set to true cond., firstly, remove occuranse of obstacle in the graph.
        /// </summary>
        /// <param name="obstacleGOToUpdate">GameObject-obstacle, for which you want to update the graph.</param>
        /// <param name="cancToken">Cancellation token for controll to async handeling</param>
        /// <param name="entitiesTasksToParallelize">List, you want to put handelling task in (if you want)</param>
        /// <param name="updateObstc">Is obstc graph updating for, already was handeled once.</param>
        public void UpdateGraphForObstacle(GameObject obstacleGOToUpdate, CancellationToken cancToken, bool updateObstc = false)
        {
            MeshCollider meshColliderInst = obstacleGOToUpdate.GetComponent <MeshCollider>();
            MeshFilter   meshFilterInst   = obstacleGOToUpdate.GetComponent <MeshFilter>();
            Terrain      terrainInst      = obstacleGOToUpdate.GetComponent <Terrain>();

            if (updateObstc)
            {
                SpaceGraph.ReleaseCellsFromObstcID(obstacleGOToUpdate.transform.GetInstanceID());
            }
            MeshDataContainer mDCInst = new MeshDataContainer()
            {
                gameObjectName = obstacleGOToUpdate.name,
                transformData  = obstacleGOToUpdate.transform,
                instanceID     = obstacleGOToUpdate.transform.GetInstanceID(),
                CTInstance     = cancToken
            };

            if (meshColliderInst && meshColliderInst.sharedMesh)
            {
                mDCInst.triangles = meshColliderInst.sharedMesh.triangles;
                mDCInst.vertices  = meshColliderInst.sharedMesh.vertices;
                HandleEntity(mDCInst, EntityType.Mesh);
            }

            if (meshFilterInst && meshFilterInst.sharedMesh)
            {
                mDCInst.triangles = meshFilterInst.sharedMesh.triangles;
                mDCInst.vertices  = meshFilterInst.sharedMesh.vertices;
                HandleEntity(mDCInst, EntityType.Mesh);
            }

            if (terrainInst)
            {
                float[,] hmArr = terrainInst.terrainData.GetHeights(0, 0, terrainInst.terrainData.heightmapResolution,
                                                                    terrainInst.terrainData.heightmapResolution);
                TerrainDataContainer tDCInst = new TerrainDataContainer()
                {
                    gameObjectName = obstacleGOToUpdate.name,
                    maxH           = terrainInst.terrainData.size.y,
                    hMArray        = hmArr,
                    hMWidth        = terrainInst.terrainData.heightmapResolution,
                    xStart         = 1,
                    xEnd           = terrainInst.terrainData.heightmapResolution,
                    zStart         = 1,
                    zEnd           = terrainInst.terrainData.heightmapResolution,
                    hX             = terrainInst.terrainData.size.x,
                    hZ             = terrainInst.terrainData.size.z,
                    terrainPos     = terrainInst.GetPosition(),
                    hMapScaleX     = terrainInst.terrainData.heightmapScale.x,
                    hMapScaleZ     = terrainInst.terrainData.heightmapScale.z,
                    instanceID     = terrainInst.transform.GetInstanceID(),
                    CTInstance     = cancToken
                };
                HandleEntity(tDCInst, EntityType.Terrain);
            }
        }
Example #3
0
        /// <summary>
        /// Performs the distribution of obstacle handeling into several subtasks for their further asynchronous execution.
        /// </summary>
        /// <param name="entityData">MeshDataContainer or TerrainDataContainer, packed as object.</param>
        /// <param name="entityType">Represent type of the <paramref name="entityData" /> to provide correct unpack from object type.</param>
        /// <param name="entitiesTasksToParallelize">List in which subtasks puts.</param>
        void HandleEntity(object entityData, EntityType entityType)
        {
            if (entityType == EntityType.Mesh)
            {
                MeshDataContainer mDCInst = ((MeshDataContainer)entityData).Clone();
                int tripletsNum           = Mathf.CeilToInt(((float)mDCInst.triangles.Length / 3) / maxAliveAsyncTasksCount);
                if (tripletsNum == 0)
                {
                    tripletsNum = 1;
                }
                while (mDCInst.triangles.Length > 0)
                {
                    int   trisIntsNum  = Mathf.Min(mDCInst.triangles.Length, tripletsNum * 3);
                    int[] distrTrisArr = mDCInst.triangles.Take(trisIntsNum).ToArray();
                    mDCInst.triangles = mDCInst.triangles.Skip(trisIntsNum).ToArray();

                    MeshDataContainer newMDCInst = ((MeshDataContainer)entityData).Clone();
                    newMDCInst.triangles = distrTrisArr;
                    asyncTasksQueue.Enqueue(new object[] { TaskType.Handling, entityType, newMDCInst });
                }
            }
            else
            {
                int xDelta, n;
                int hMWidth = ((TerrainDataContainer)entityData).hMWidth;
                if (maxAliveAsyncTasksCount == 1)
                {
                    xDelta = hMWidth;
                    n      = 1;
                }
                else
                {
                    xDelta = Mathf.CeilToInt((float)hMWidth / maxAliveAsyncTasksCount / 16);
                    n      = Mathf.CeilToInt((float)hMWidth / xDelta);
                }
                for (var i = 0; i < n; ++i)
                {
                    TerrainDataContainer tDCInst = ((TerrainDataContainer)entityData).Clone();
                    tDCInst.xStart = i * xDelta + 1;
                    tDCInst.xEnd   = Mathf.Min(i * xDelta + xDelta + 1, hMWidth);
                    asyncTasksQueue.Enqueue(new object[] { TaskType.Handling, entityType, tDCInst });
                }
            }
        }
Example #4
0
            public MeshDataContainer Clone()
            {
                MeshDataContainer cloneInstance = new MeshDataContainer
                {
                    transformData = this.transformData
                };

                cloneInstance.vertices = new Vector3[this.vertices.Length];
                this.vertices.CopyTo(cloneInstance.vertices, 0);

                cloneInstance.triangles = new int[this.triangles.Length];
                this.triangles.CopyTo(cloneInstance.triangles, 0);


                cloneInstance.instanceID     = this.instanceID;
                cloneInstance.CTInstance     = this.CTInstance;
                cloneInstance.gameObjectName = this.gameObjectName;
                return(cloneInstance);
            }
Example #5
0
        /// <summary>
        /// Perfoms handeling of a mesh. Must be running asyncronously.
        /// </summary>
        /// <param name="inpData">Mesh to handle data, packed from MeshDataContainer instance. </param>
        void AsyncMeshMethod(object inpData)
        {
            try
            {
                if (agressiveUseMultithreading)
                {
                    Interlocked.Increment(ref aliveHandelingTasksCount);
                }
                MeshDataContainer mDCInstance = (MeshDataContainer)inpData;
                int curTaskId = uniqeHandlingTaskID;
                Interlocked.Increment(ref uniqeHandlingTaskID);
                AsyncTaskDataContainer aTDCInstance = new AsyncTaskDataContainer
                {
                    gameObjectName = mDCInstance.gameObjectName,
                    threadName     = Thread.CurrentThread.Name,
                    uniqeTaskID    = curTaskId,
                    trisCount      = mDCInstance.triangles.Length / 3,
                    verticesCount  = mDCInstance.vertices.Length
                };
                aliveTasksDict.TryAdd(curTaskId, aTDCInstance);
                int[] triangles = null;
                int   p0i       = 0;
                int   p1i       = 0;
                int   p2i       = 0;

                Vector3[] vertices = mDCInstance.vertices;
                triangles = mDCInstance.triangles;
                CustomTransform meshCTransf = mDCInstance.transformData;
                int             instanceID  = mDCInstance.instanceID;


                for (var i = 1; i <= mDCInstance.triangles.Length / 3; ++i)
                {
                    try
                    {
                        if ((broadcastCancToken.IsCancellationRequested) ||
                            ((CancellationToken)mDCInstance.CTInstance).IsCancellationRequested)
                        {
                            return;
                        }
                        p0i = triangles[(i - 1) * 3];
                        p1i = triangles[(i - 1) * 3 + 1];
                        p2i = triangles[(i - 1) * 3 + 2];
                        Vector3 p0 = vertices[triangles[(i - 1) * 3]];
                        Vector3 p1 = vertices[triangles[(i - 1) * 3 + 1]];
                        Vector3 p2 = vertices[triangles[(i - 1) * 3 + 2]];

                        OccupyCellsForATriangle(
                            meshCTransf.position + meshCTransf.rotation * (Vector3.Scale(meshCTransf.localScale, p0)),
                            meshCTransf.position + meshCTransf.rotation * (Vector3.Scale(meshCTransf.localScale, p1)),
                            meshCTransf.position + meshCTransf.rotation * (Vector3.Scale(meshCTransf.localScale, p2)),
                            instanceID
                            );
                    }
                    catch (Exception ex)
                    {
                        if (!isPrimaryProcessingCompleted)
                        {
                            Interlocked.Increment(ref processedTrisCount);
                        }
                        throw (ex);
                    }
                }

                aliveTasksDict.TryRemove(curTaskId, out aTDCInstance);
                Interlocked.Decrement(ref aliveHandelingTasksCount);
                if (!isPrimaryProcessingCompleted && processedTrisCount >= totalTrisCount && aliveHandelingTasksCount == 0)
                {
                    NotifyRediness();
                }
            }
            catch (Exception ex)
            {
                UnityEngine.Debug.Log(ex.Message);
            }
        }
    public static void BakeLights()
    {
        DateTime bakeStart = DateTime.Now;

        // current selection
        GameObject[] selection = Selection.gameObjects;

        List <MeshFilter> meshes = new List <MeshFilter>();

        // gather meshes in selection
        foreach (GameObject go in selection)
        {
            meshes.AddRange(go.GetComponentsInChildren <MeshFilter>());
        }
        if (meshes.Count == 0)
        {
            EditorUtility.DisplayDialog("Error", "No meshes in selection", "ok");
            return;
        }

        // mesh renderers allow access to additional mesh data
        List <MeshRenderer> meshRenderers = new List <MeshRenderer>();

        // gather meshes in selection build 1 to 1 list of mesh filters to mesh renderers
        foreach (MeshFilter filter in meshes)
        {
            MeshRenderer mr = filter.GetComponent <MeshRenderer>();
            if (mr != null)
            {
                meshRenderers.Add(mr);
            }
        }

        if (meshes.Count != meshRenderers.Count)
        {
            EditorUtility.DisplayDialog("Error", "MeshRenderers are not 1 to 1 with Mesh Filters", "ok");
            return;
        }

        List <Light> lights = new List <Light>();

        // Gather lights
        GameObject[] roots = SceneManager.GetActiveScene().GetRootGameObjects();
        foreach (GameObject go in roots)
        {
            if (go.activeSelf)
            {
                lights.AddRange(go.GetComponentsInChildren <Light>());
            }
        }

        int workerThreadCount = Math.Max(7, Environment.ProcessorCount - 1);

        ThreadPool.SetMaxThreads(workerThreadCount, workerThreadCount);
        ThreadPool.SetMinThreads(1, 1);

        // create new meshes with lights baked in
        for (int i = 0, count = meshes.Count; i < count; ++i)
        {
            Matrix4x4 worldM = meshes[i].gameObject.transform.localToWorldMatrix;

            // create new mesh to hold color data
            for (int c = 0; c < 3; ++c)
            {
                m_basisValues[c] = new List <Vector3>();
            }


            ManualResetEvent[] waitHandles = new ManualResetEvent[workerThreadCount];
            for (int e = 0; e < workerThreadCount; ++e)
            {
                waitHandles[e] = new ManualResetEvent(false);
            }

            int itemsPerThread = meshes[i].sharedMesh.vertexCount / workerThreadCount;
            int remainder      = meshes[i].sharedMesh.vertexCount % workerThreadCount;

            // store basis results here then combine into final result
            List <List <Vector3>[]> tempBasisValues = new List <List <Vector3>[]>();

            for (int t = 0; t < workerThreadCount; ++t)
            {
                tempBasisValues.Add(new List <Vector3> [3]);

                for (int c = 0; c < 3; ++c)
                {
                    tempBasisValues[t][c] = new List <Vector3>();
                }

                // create cache friendly lists of data
                SOAVertex verts = new SOAVertex(meshes[i].sharedMesh.vertices.Length);
                verts.vertices = meshes[i].sharedMesh.vertices;
                verts.normals  = meshes[i].sharedMesh.normals;
                verts.tangents = meshes[i].sharedMesh.tangents;

                LightSOA lightsSoa = new LightSOA(lights);

                object context = new object[] {
                    waitHandles[t],
                    verts,
                    worldM,
                    lightsSoa,
                    tempBasisValues[t],           // output list
                    itemsPerThread,               // number of verts to process
                    itemsPerThread *t,            // vert offset
                    remainder,                    // last thread will process remainder
                    t == (workerThreadCount - 1), // is last
                    t                             // id
                };

                ThreadPool.QueueUserWorkItem(ProcessVertex, context);
                //ProcessVertex(context);
            }

            // wait for jobs to finish
            WaitHandle.WaitAll(waitHandles);

            // collect basis value results
            for (int t = 0; t < workerThreadCount; ++t)
            {
                m_basisValues[0].AddRange(tempBasisValues[t][0]);
                m_basisValues[1].AddRange(tempBasisValues[t][1]);
                m_basisValues[2].AddRange(tempBasisValues[t][2]);
            }

            const int uvOffset = 1;
            // if vertices is not set than we cannot set UVS
            // these vertices seem to be used then in place of the primary meshes vertices
            Mesh colorData = new Mesh();
            colorData.vertices = meshes[i].sharedMesh.vertices;
            colorData.SetUVs(uvOffset + 0, m_basisValues[0]);
            colorData.SetUVs(uvOffset + 1, m_basisValues[1]);
            colorData.SetUVs(uvOffset + 2, m_basisValues[2]);
            colorData.UploadMeshData(true);


            string assetPath = "Assets/BakedLighting";

            if (!Directory.Exists(assetPath))
            {
                Directory.CreateDirectory(assetPath);
            }

            AssetDatabase.CreateAsset(colorData, assetPath + "/" + meshRenderers[i].GetInstanceID() + ".asset");
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            colorData = AssetDatabase.LoadAssetAtPath <Mesh>(assetPath + "/" + meshRenderers[i].GetInstanceID() + ".asset");

            MeshDataContainer meshDataContainer = meshRenderers[i].GetComponent <MeshDataContainer>();

            if (meshDataContainer == null)
            {
                meshDataContainer = meshRenderers[i].gameObject.AddComponent <MeshDataContainer>();
            }

            meshDataContainer.m_mesh = colorData;

            meshRenderers[i].additionalVertexStreams = colorData;

            EditorUtility.SetDirty(meshDataContainer.m_mesh);
            EditorUtility.SetDirty(meshDataContainer);
            EditorUtility.SetDirty(meshRenderers[i].gameObject);
            AssetDatabase.SaveAssets();
        }

        Debug.Log("Bake time: " + (DateTime.Now - bakeStart).TotalSeconds + " seconds");
    }