Пример #1
0
        /// <summary>
        /// Updates the mesh by setting its data given the last valid vertex index and the last
        /// valid triangle index. Be aware that by default the data is set starting from index 0.
        /// </summary>
        /// <param name="lastValidVertexIndex"></param>
        /// <param name="lastValidTriIndex"></param>
        protected void UpdateMesh(int lastValidVertexIndex, int lastValidTriIndex)
        {
            sampler.Begin();

            // Note: this might be called in between job completions so it could be moved away.
            mesh.Clear(false);

            MeshUpdateFlags updateFlags = ~MeshUpdateFlags.Default;

            mesh.SetVertices(vertices, 0, lastValidVertexIndex, updateFlags);
            mesh.SetIndices(tris, 0, lastValidTriIndex, MeshTopology.Triangles, 0, false);
            if (UseNormals)
            {
                mesh.SetNormals(normals, 0, lastValidVertexIndex, updateFlags);
            }
            if (UseUvs)
            {
                mesh.SetUVs(0, uvs, 0, lastValidVertexIndex, updateFlags);
            }
            if (UseVertexColors)
            {
                mesh.SetColors(colors, 0, lastValidVertexIndex, updateFlags);
            }

            mesh.RecalculateBounds();

            sampler.End();
        }
Пример #2
0
    void InitMeshFilter()
    {
        ReleaseMeshFilter();

        int vertexCount = 100;
        int indexCount  = 100;

        meshGrass = new Mesh();

        // 宣告 vertex buffer 結構
        VertexAttributeDescriptor[] layouts = new VertexAttributeDescriptor[]
        {
            new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3)
        };

        meshGrass.SetVertexBufferParams(vertexCount, layouts);

        // 宣告 index buffer 結構
        meshGrass.SetIndexBufferParams(indexCount, IndexFormat.UInt16);

        MeshUpdateFlags flag = MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontRecalculateBounds;

        meshGrass.SetVertexBufferData(getRandomPosition(vertexCount, 10f), 0, 0, vertexCount, 0, flag);
        meshGrass.SetIndexBufferData(getSequenceIndices(indexCount), 0, 0, indexCount, flag);

        // 設定 Mesh Topologiy
        SubMeshDescriptor desc = new SubMeshDescriptor(0, indexCount, MeshTopology.Points);

        meshGrass.SetSubMesh(0, desc, flag);


        meshGrass.bounds = new Bounds(Vector3.zero, new Vector3(1000f, 5f, 1000f));

        this.GetComponent <MeshFilter>().sharedMesh = meshGrass;
    }
Пример #3
0
 internal void ApplyToMeshAndDispose(Mesh mesh, MeshUpdateFlags flags)
 {
     if (!mesh.canAccess)
     {
         throw new InvalidOperationException($"Not allowed to access vertex data on mesh '{mesh.name}' (isReadable is false; Read/Write must be enabled in import settings)");
     }
     ApplyToMeshImpl(mesh, m_Ptrs[0], flags);
     Dispose();
 }
Пример #4
0
    public static void SetVertexDataToMesh(Mesh mesh, NativeArray <Vertex> vertices)
    {
        MeshUpdateFlags flags =
            MeshUpdateFlags.DontResetBoneBounds |
            MeshUpdateFlags.DontRecalculateBounds |
            MeshUpdateFlags.DontValidateIndices |
            MeshUpdateFlags.DontNotifyMeshUsers;

        mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length, 0, flags);
    }
Пример #5
0
        PopulateMeshData()
        {
            Profiler.BeginSample("PopulateMeshData");

            foreach (var map in attributes)
            {
                map.Dispose();
            }
            attributes = null;

            Profiler.BeginSample("MeshAssign");

            const MeshUpdateFlags flags = DracoMeshLoader.defaultMeshUpdateFlags;

#if !DRACO_MESH_DATA
            for (var streamIndex = 0; streamIndex < streamCount; streamIndex++)
            {
                mesh.SetVertexBufferData(vData[streamIndex], 0, 0, vData[streamIndex].Length, streamIndex, flags);
            }

            mesh.SetIndexBufferData(indices, 0, 0, indices.Length);
            var indicesCount = indices.Length;
#endif

            mesh.subMeshCount = 1;
            var submeshDescriptor = new SubMeshDescriptor(0, indicesCount)
            {
                firstVertex = 0, baseVertex = 0, vertexCount = mesh.vertexCount
            };
            mesh.SetSubMesh(0, submeshDescriptor, flags);
            Profiler.EndSample(); // CreateUnityMesh.CreateMesh

#if DRACO_MESH_DATA
#else
            Profiler.BeginSample("Dispose");
            indices.Dispose();
            foreach (var nativeArray in vData)
            {
                nativeArray.Dispose();
            }
            Profiler.EndSample();
#endif
            Profiler.EndSample();

#if DRACO_MESH_DATA
            return(true);
#else
            return(mesh);
#endif
        }
Пример #6
0
        void CreateMeshForEachSubMesh(
            NativeArray <CombinedVertex> vertices,
            NativeArray <int> triangles,
            NativeArray <SubMesh> subMeshes)
        {
            const MeshUpdateFlags flags = MeshUpdateFlags.DontRecalculateBounds;

            foreach (var subMesh in subMeshes)
            {
                var vertexSlice    = vertices.GetSubArray(subMesh.VertexStartIndex, subMesh.VertexCount);
                var trianglesSlice = triangles.GetSubArray(subMesh.TriangleStartIndex, subMesh.TriangleCount);
                var surfaceInfo    = GetRoadSurfaceInfo(subMesh.Material);
                var meshObject     = new GameObject(surfaceInfo.label)
                {
                    isStatic = true
                };
                meshObject.transform.parent = Parameters.parentObject.transform;

                var filter = meshObject.AddComponent <MeshFilter>();
                var mesh   = new Mesh();
                var layout = new[]
                {
                    new VertexAttributeDescriptor(VertexAttribute.Position),
                    new VertexAttributeDescriptor(VertexAttribute.Normal),
                    new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2),
                };
                mesh.SetVertexBufferParams(vertexSlice.Length, layout);
                mesh.SetVertexBufferData(vertexSlice, 0, 0, vertexSlice.Length, 0, flags);
                mesh.SetIndexBufferParams(trianglesSlice.Length, IndexFormat.UInt32);
                mesh.SetIndexBufferData(trianglesSlice, 0, 0, trianglesSlice.Length, flags);
                mesh.SetSubMesh(0, new SubMeshDescriptor(0, subMesh.TriangleCount), flags);
                mesh.RecalculateBounds();
                filter.sharedMesh = mesh;

                var renderer = meshObject.AddComponent <MeshRenderer>();
                renderer.sharedMaterial = surfaceInfo.material;

                if (Parameters.addMeshCollider)
                {
                    meshObject.AddComponent <MeshCollider>();
                }

#if PERCEPTION_PRESENT
                var label = meshObject.AddComponent <Labeling>();
                label.labels.Add(surfaceInfo.label);
#endif
            }
        }
Пример #7
0
 internal void ApplyToMeshesAndDispose(Mesh[] meshes, MeshUpdateFlags flags)
 {
     for (int i = 0; i < m_Length; ++i)
     {
         Mesh m = meshes[i];
         if (m == null)
         {
             throw new ArgumentNullException(nameof(meshes), $"Mesh at index {i} is null");
         }
         if (!m.canAccess)
         {
             throw new InvalidOperationException($"Not allowed to access vertex data on mesh '{m.name}' at array index {i} (isReadable is false; Read/Write must be enabled in import settings)");
         }
     }
     ApplyToMeshesImpl(meshes, m_Ptrs, m_Length, flags);
     Dispose();
 }
Пример #8
0
    void FillDiamond(ref Mesh diamond, ref DiamondData data)
    {
        _vertices[0].pos.x = data.pt1.x;
        _vertices[0].pos.y = data.pt1.y;
        _vertices[0].uv.x  = data.uv1.x;
        _vertices[0].uv.y  = data.uv1.y;

        _vertices[1].pos.x = data.pt2.x;
        _vertices[1].pos.y = data.pt2.y;
        _vertices[1].uv.x  = data.uv2.x;
        _vertices[1].uv.y  = data.uv2.y;

        _vertices[2].pos.x = data.pt3.x;
        _vertices[2].pos.y = data.pt3.y;
        _vertices[2].uv.x  = data.uv3.x;
        _vertices[2].uv.y  = data.uv3.y;

        _vertices[3].pos.x = data.pt4.x;
        _vertices[3].pos.y = data.pt4.y;
        _vertices[3].uv.x  = data.uv4.x;
        _vertices[3].uv.y  = data.uv4.y;

        _vertices[4].pos.x = data.pt5.x;
        _vertices[4].pos.y = data.pt5.y;
        _vertices[4].uv.x  = data.uv5.x;
        _vertices[4].uv.y  = data.uv5.y;

        MeshUpdateFlags flag = GetMeshUpdateFlags();

        const int indexCount  = 9;
        const int vertexCount = 5;

        // 設定 Mesh Topologiy
        SubMeshDescriptor desc = new SubMeshDescriptor(0, indexCount, MeshTopology.Triangles);

        diamond.SetSubMesh(0, desc, flag);

        // 宣告 index buffer 結構
        diamond.SetIndexBufferParams(indexCount, IndexFormat.UInt16);

        // 宣告 vertex buffer 結構
        diamond.SetVertexBufferParams(vertexCount, _layouts);

        diamond.SetVertexBufferData(_vertices, 0, 0, vertexCount, 0, flag);
        diamond.SetIndexBufferData(_indices, 0, 0, indexCount, flag);
    }
Пример #9
0
        public void ApplyMeshData(ref Mesh mesh)
        {
            // 'is object' to bypass unity lifetime check for null
            if (!(mesh is object))
            {
                throw new NullReferenceException(nameof(mesh));
            }
            else
            {
                mesh.Clear();
            }

            if ((_Vertices.Count == 0) || (_Triangles.Count == 0))
            {
                return;
            }

            if ((int)((_Vertices.Count / 2f) * 1.5f) != _Triangles.Sum(triangles => triangles.Count))
            {
                throw new ArgumentOutOfRangeException($"Sum of all {_Triangles} should be 1.5x as many vertices.");
            }

            const MeshUpdateFlags default_flags = MeshUpdateFlags.DontRecalculateBounds
                                                  | MeshUpdateFlags.DontValidateIndices
                                                  | MeshUpdateFlags.DontResetBoneBounds;

            mesh.SetVertexBufferParams(_Vertices.Count, _Layout);
            mesh.SetVertexBufferData(_Vertices, 0, 0, _Vertices.Count, 0, default_flags);

            mesh.subMeshCount = _Triangles.Count;

            foreach (List <int> triangles in _Triangles.Where(triangles => triangles.Count != 0))
            {
                mesh.SetIndexBufferParams(triangles.Count, IndexFormat.UInt32);
                mesh.SetIndexBufferData(triangles, 0, 0, triangles.Count, default_flags);
                mesh.SetSubMesh(0, new SubMeshDescriptor(0, triangles.Count), default_flags);
            }

            mesh.bounds = new Bounds(new float3(GenerationConstants.CHUNK_SIZE / 2), new float3(GenerationConstants.CHUNK_SIZE));
        }
Пример #10
0
        public override void ApplyOnMesh(UnityEngine.Mesh msh, MeshUpdateFlags flags = MeshUpdateFlags.Default)
        {
            Profiler.BeginSample("ApplyOnMesh");
            if (vad == null)
            {
                CreateDescriptors();
            }

            Profiler.BeginSample("SetVertexBufferParams");
            msh.SetVertexBufferParams(vData.Length, vad);
            Profiler.EndSample();

            Profiler.BeginSample("SetVertexBufferData");
            int stream = 0;

            msh.SetVertexBufferData(vData, 0, 0, vData.Length, stream, flags);
            stream++;
            Profiler.EndSample();

            if (texCoords != null)
            {
                texCoords.ApplyOnMesh(msh, stream, flags);
                stream++;
            }

            if (colors != null)
            {
                colors.ApplyOnMesh(msh, stream, flags);
                stream++;
            }

            if (bones != null)
            {
                bones.ApplyOnMesh(msh, stream, flags);
                stream++;
            }

            Profiler.EndSample();
        }
Пример #11
0
    static private bool createMesh(ref LodVertex[] vertices, ref ushort[] indices, out Mesh mesh)
    {
        mesh = null;

        if (vertices.Length == 0 || indices.Length == 0)
        {
            return(false);
        }

        mesh = new Mesh();

        // 宣告 vertex buffer 結構
        VertexAttributeDescriptor[] layouts = new VertexAttributeDescriptor[]
        {
            new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
            new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UNorm8, 4),
            new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.UInt32, 1)
        };

        mesh.SetVertexBufferParams(vertices.Length, layouts);

        // 宣告 index buffer 結構
        mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt16);

        MeshUpdateFlags flag = MeshUpdateFlags.Default;

        mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length, 0, flag);
        mesh.SetIndexBufferData(indices, 0, 0, indices.Length, flag);

        // 設定 Mesh Topologiy
        SubMeshDescriptor desc = new SubMeshDescriptor(0, indices.Length, MeshTopology.Triangles);

        mesh.SetSubMesh(0, desc, flag);

        return(true);
    }
Пример #12
0
    void FillTriangle(ref Mesh triangle, ref TriangleData data)
    {
        _vertices[0].pos.x = data.pt1.x;
        _vertices[0].pos.y = data.pt1.y;
        _vertices[0].uv.x  = data.uv1.x;
        _vertices[0].uv.y  = data.uv1.y;

        _vertices[1].pos.x = data.pt2.x;
        _vertices[1].pos.y = data.pt2.y;
        _vertices[1].uv.x  = data.uv2.x;
        _vertices[1].uv.y  = data.uv2.y;

        _vertices[2].pos.x = data.pt3.x;
        _vertices[2].pos.y = data.pt3.y;
        _vertices[2].uv.x  = data.uv3.x;
        _vertices[2].uv.y  = data.uv3.y;

        MeshUpdateFlags flag = GetMeshUpdateFlags();

        const int indexCount  = 3;
        const int vertexCount = 3;

        // 設定 Mesh Topologiy
        SubMeshDescriptor desc = new SubMeshDescriptor(0, indexCount, MeshTopology.Triangles);

        triangle.SetSubMesh(0, desc, flag);

        // 宣告 index buffer 結構
        triangle.SetIndexBufferParams(indexCount, IndexFormat.UInt16);

        // 宣告 vertex buffer 結構
        triangle.SetVertexBufferParams(vertexCount, _layouts);

        triangle.SetVertexBufferData(_vertices, 0, 0, vertexCount, 0, flag);
        triangle.SetIndexBufferData(_indices, 0, 0, indexCount, flag);
    }
Пример #13
0
 [NativeMethod(IsThreadSafe = true, ThrowsException = true)] static extern void SetSubMeshImpl(IntPtr self, int index, SubMeshDescriptor desc, MeshUpdateFlags flags);
Пример #14
0
 public abstract void ApplyOnMesh(UnityEngine.Mesh msh, int stream, MeshUpdateFlags flags = PrimitiveCreateContextBase.defaultMeshUpdateFlags);
Пример #15
0
 public override void ApplyOnMesh(UnityEngine.Mesh msh, int stream, MeshUpdateFlags flags = PrimitiveCreateContextBase.defaultMeshUpdateFlags)
 {
     Profiler.BeginSample("ApplyUVs");
     msh.SetVertexBufferData(vData, 0, 0, vData.Length, stream, flags);
     Profiler.EndSample();
 }
Пример #16
0
 public abstract void ApplyOnMesh(UnityEngine.Mesh msh, MeshUpdateFlags flags = MeshUpdateFlags.Default);
Пример #17
0
    public static bool Generate(float size, out Mesh _mesh)
    {
        const int VERTICES_COUNT = 8;

        float halfSize = size * 0.5f;

        // vertex
        CubeVertex[] vertices = new CubeVertex[VERTICES_COUNT];
        vertices[0].pos = new Vector3(-halfSize, -halfSize, -halfSize);
        vertices[1].pos = new Vector3(-halfSize, halfSize, -halfSize);
        vertices[2].pos = new Vector3(halfSize, halfSize, -halfSize);
        vertices[3].pos = new Vector3(halfSize, -halfSize, -halfSize);
        vertices[4].pos = new Vector3(-halfSize, -halfSize, halfSize);
        vertices[5].pos = new Vector3(-halfSize, halfSize, halfSize);
        vertices[6].pos = new Vector3(halfSize, halfSize, halfSize);
        vertices[7].pos = new Vector3(halfSize, -halfSize, halfSize);

        for (int i = 0; i < VERTICES_COUNT; ++i)
        {
            vertices[i].normal = Vector3.Normalize(vertices[i].pos);
        }

        // index
        ushort[] indices = new ushort[] {
            0, 1, 2,
            2, 3, 0,
            0, 4, 5,
            5, 1, 0,
            2, 6, 7,
            7, 3, 2,
            7, 6, 5,
            5, 4, 7,
            1, 5, 6,
            6, 2, 1,
            4, 0, 3,
            3, 7, 4
        };

        MeshUpdateFlags flag = MeshUpdateFlags.Default;

        VertexAttributeDescriptor[] layouts = new VertexAttributeDescriptor[]
        {
            new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
            new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
        };

        _mesh = new Mesh();

        // 宣告 index buffer 結構
        _mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt16);

        // 宣告 vertex buffer 結構
        _mesh.SetVertexBufferParams(VERTICES_COUNT, layouts);

        _mesh.SetVertexBufferData(vertices, 0, 0, VERTICES_COUNT, 0, flag);
        _mesh.SetIndexBufferData(indices, 0, 0, indices.Length, flag);

        // 設定 Mesh Topologiy
        SubMeshDescriptor desc = new SubMeshDescriptor(0, indices.Length, MeshTopology.Triangles);

        _mesh.SetSubMesh(0, desc, flag);

        return(true);
    }
Пример #18
0
        public override Primitive?CreatePrimitive()
        {
            Profiler.BeginSample("CreatePrimitive");
            jobHandle.Complete();
            var msh = new UnityEngine.Mesh();

            msh.name = mesh.name;

            MeshUpdateFlags flags = MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontValidateIndices;

            vertexData.ApplyOnMesh(msh, flags);

            Profiler.BeginSample("SetIndices");
            int indexCount = 0;

            for (int i = 0; i < indices.Length; i++)
            {
                indexCount += indices[i].Length;
            }
            Profiler.BeginSample("SetIndexBufferParams");
            msh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); //TODO: UInt16 maybe?
            Profiler.EndSample();
            msh.subMeshCount = indices.Length;
            indexCount       = 0;
            for (int i = 0; i < indices.Length; i++)
            {
                Profiler.BeginSample("SetIndexBufferData");
                msh.SetIndexBufferData(indices[i], 0, indexCount, indices[i].Length, flags);
                Profiler.EndSample();
                Profiler.BeginSample("SetSubMesh");
                msh.SetSubMesh(i, new SubMeshDescriptor(indexCount, indices[i].Length, topology), flags);
                Profiler.EndSample();
                indexCount += indices[i].Length;
            }
            Profiler.EndSample();

            if (vertexData.calculateNormals)
            {
                Profiler.BeginSample("RecalculateNormals");
                msh.RecalculateNormals();
                Profiler.EndSample();
            }
            if (vertexData.calculateTangents)
            {
                Profiler.BeginSample("RecalculateTangents");
                msh.RecalculateTangents();
                Profiler.EndSample();
            }

            Profiler.BeginSample("RecalculateBounds");
            msh.RecalculateBounds(); // TODO: make optional! maybe calculate bounds in Job.
            Profiler.EndSample();

#if GLTFAST_KEEP_MESH_DATA
            Profiler.BeginSample("UploadMeshData");
            msh.UploadMeshData(false);
            Profiler.EndSample();
#else
            /// Don't upload explicitely. Unity takes care of upload on demand/deferred

            // Profiler.BeginSample("UploadMeshData");
            // msh.UploadMeshData(true);
            // Profiler.EndSample();
#endif

            Profiler.BeginSample("Dispose");
            Dispose();
            Profiler.EndSample();

            Profiler.EndSample();
            return(new Primitive(msh, materials));
        }
Пример #19
0
 public void SetSubMesh(int index, SubMeshDescriptor desc, MeshUpdateFlags flags = MeshUpdateFlags.Default)
 {
     CheckWriteAccess();
     SetSubMeshImpl(m_Ptr, index, desc, flags);
 }
Пример #20
0
 [NativeThrows] static extern unsafe void ApplyToMeshesImpl([NotNull] Mesh[] meshes, IntPtr *datas, int count, MeshUpdateFlags flags);
Пример #21
0
    // Display routine for 2d examples in the main program
    void display2()
    {
        // to push and pop location and angle
        Stack <float> positions = new Stack <float>();
        Stack <float> angles    = new Stack <float>();

        // current angle and position
        float  angle    = 0f;
        float3 position = new float3(0, 0, 0);
        float  posy     = 0.0f;
        float  posx     = 0.0f;

        // positions to draw towards
        float3 newPosition;
        float2 rotated;

        // start at 0,0,0

        // Apply the drawing rules to the string given to us
        for (int i = 0; i < lang.Count; i++)
        {
            byte buff = lang[i];
            switch (buff)
            {
            case 0:
                // draw a line ending in a leaf
                posy       += initial_length;
                newPosition = new float3(position.x, posy, 0);
                rotated     = rotate(position, new float3(position.x, posy, 0), angle);
                newPosition = new float3(rotated.x, rotated.y, 0);
                addLineToMesh(lineMesh, position, new float3(rotated.x, rotated.y, 0), Color.green);
                //drawLSystemLine(position, new Vector3(rotated.x, rotated.y, 0), line, Color.red);
                // set up for the next draw
                position = newPosition;
                posx     = newPosition.x;
                posy     = newPosition.y;
                addCircleToMesh(lineMesh, 0.45f, 0.45f, position, Color.magenta);
                break;

            case 1:
                // draw a line
                posy       += initial_length;
                newPosition = new float3(position.x, posy, 0);
                rotated     = rotate(position, new float3(position.x, posy, 0), angle);
                newPosition = new float3(rotated.x, rotated.y, 0);
                //drawLSystemLine(position, newPosition, line, Color.green);
                addLineToMesh(lineMesh, position, newPosition, Color.green);
                // set up for the next draw
                position = newPosition;
                posx     = newPosition.x;
                posy     = newPosition.y;
                break;

            case 6:
                //[: push position and angle, turn left 45 degrees
                positions.Push(posy);
                positions.Push(posx);
                float currentAngle = angle;
                angles.Push(currentAngle);
                angle -= 45;
                break;

            case 9:
                //]: pop position and angle, turn right 45 degrees
                posx     = positions.Pop();
                posy     = positions.Pop();
                position = new float3(posx, posy, 0);
                angle    = angles.Pop();
                angle   += 45;
                break;

            default: break;
            }
            // after we recreate the mesh we need to assign it to the original object
            MeshUpdateFlags flags = MeshUpdateFlags.DontNotifyMeshUsers & MeshUpdateFlags.DontRecalculateBounds &
                                    MeshUpdateFlags.DontResetBoneBounds & MeshUpdateFlags.DontValidateIndices;

            // set vertices
            var layout = new[]
            {
                new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
                new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UNorm8, 4)
            };
            lineMesh.SetVertexBufferParams(vertices.Count, layout);
            lineMesh.SetVertexBufferData(vertices, 0, 0, vertices.Count, 0, flags);

            // set indices
            UnityEngine.Rendering.IndexFormat format = IndexFormat.UInt32;
            lineMesh.SetIndexBufferParams(indices.Count, format);
            lineMesh.SetIndexBufferData(indices, 0, 0, indices.Count, flags);

            // set submesh
            SubMeshDescriptor desc = new SubMeshDescriptor(0, indices.Count, MeshTopology.Lines);
            desc.bounds      = new Bounds();
            desc.baseVertex  = 0;
            desc.firstVertex = 0;
            desc.vertexCount = vertices.Count;
            lineMesh.SetSubMesh(0, desc, flags);
        }
    }
Пример #22
0
 public override void ApplyOnMesh(UnityEngine.Mesh msh, int stream, MeshUpdateFlags flags = MeshUpdateFlags.Default)
 {
     Profiler.BeginSample("ApplyBones");
     msh.SetVertexBufferData(vData, 0, 0, vData.Length, stream, flags);
     Profiler.EndSample();
 }
Пример #23
0
        internal void Rebuild()
        {
            // no logic during play.
            if (Application.isPlaying)
            {
                return;
            }

            // create a new mesh or clear the existing one.
            Mesh mesh = ResetDecalMesh();

            // update the flags we need to tell if we have to rebuild the decal mesh.
            UpdateDirtyFlags();

            // find all mesh colliders that intersect with the decal projector box.
            List <MeshCollider> meshColliders = FindMeshColliders();
            int meshCollidersCount            = meshColliders.Count;

            if (meshCollidersCount == 0)
            {
                return;                          // early out.
            }
            List <Vector3> vertices  = new List <Vector3>(6 * meshCollidersCount);
            List <int>     triangles = new List <int>(6 * meshCollidersCount);
            List <Vector2> uvs       = new List <Vector2>(6 * meshCollidersCount);

            // precalculate values that never change from this point on.

            MeshUpdateFlags meshUpdateFlags = MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontResetBoneBounds;

            Bounds projectorBounds = GetBounds();

            projectorBounds.center = transform.position - projectorBounds.center;

            Vector3 r = transform.TransformVector(Vector3.right * 0.5f);
            Vector3 f = transform.TransformVector(Vector3.forward * 0.5f);
            Vector3 u = transform.TransformVector(Vector3.up * 0.5f);

            float uscale  = transform.InverseTransformVector(transform.right).x *uvTiling.x;
            float vscale  = transform.InverseTransformVector(transform.up).y *uvTiling.y;
            float uoffset = 0.5f * uvTiling.x - uvOffset.x;
            float voffset = 0.5f * uvTiling.y + uvOffset.y;

            Clipping clipping = new Clipping(new Plane[] {
                new Plane(-r, transform.position + r),
                new Plane(r, transform.position - r),
                new Plane(-f, transform.position + f),
                new Plane(f, transform.position - f),
                new Plane(-u, transform.position + u + f),
                new Plane(u, transform.position - u + f)
            });

            // create a horizontal and vertical plane through the projector box.
            // the distance of the vertices to the planes are used to calculate UV coordinates.
            Plane hplane = new Plane(u, transform.position);
            Plane vplane = new Plane(r, transform.position);

            float maxAngleCos       = Mathf.Cos(Mathf.Deg2Rad * (180.0f - maxAngle));
            float zOffsetMultiplier = 0.001f + (zOffset * 0.001f);

            // optimization: recycle the same polygon list used for clipping.
            Vector3[] poly      = new Vector3[8];
            int       polyCount = 0;

            for (int mc = 0; mc < meshCollidersCount; mc++)
            {
                var  meshCollider = meshColliders[mc];
                Mesh colliderMesh = meshCollider.sharedMesh;

                // make sure an octree of this mesh exists.
                if (!meshTriangleOctrees.ContainsKey(colliderMesh))
                {
                    meshTriangleOctrees.Add(colliderMesh, new BoundsOctree <BoundsOctreeTriangle>(8.0f, meshCollider.transform.position, 4.0f, 1.0f));

                    // get the collider vertices and triangles.
                    Vector3[] colliderVertices  = colliderMesh.vertices;
                    int[]     colliderTriangles = colliderMesh.GetTriangles(0);

                    // build the octree.
                    for (int i = 0; i < colliderTriangles.Length; i += 3)
                    {
                        // fetch a triangle from the collider.
                        Vector3 colliderVertex1 = colliderVertices[colliderTriangles[i]];
                        Vector3 colliderVertex2 = colliderVertices[colliderTriangles[i + 1]];
                        Vector3 colliderVertex3 = colliderVertices[colliderTriangles[i + 2]];

                        // apply any modification from their transform.
                        colliderVertex1 = meshCollider.transform.TransformPoint(colliderVertex1);
                        colliderVertex2 = meshCollider.transform.TransformPoint(colliderVertex2);
                        colliderVertex3 = meshCollider.transform.TransformPoint(colliderVertex3);

                        // now the mesh vertices are in world space 1:1 to how they appear in the scene.

                        // calculate the triangle bounds.
                        Bounds triangleBounds = new Bounds(colliderVertex1, Vector3.zero);
                        triangleBounds.Encapsulate(colliderVertex2);
                        triangleBounds.Encapsulate(colliderVertex3);

                        // add the triangle to the octree.
                        meshTriangleOctrees[colliderMesh].Add(new BoundsOctreeTriangle()
                        {
                            vertex1 = colliderVertex1, vertex2 = colliderVertex2, vertex3 = colliderVertex3, normal = GetNormal(colliderVertex1, colliderVertex2, colliderVertex3)
                        }, triangleBounds);
                    }
                }

                // find all triangles inside of the projector bounds using the octree.
                List <BoundsOctreeTriangle> trianglesInsideProjector = new List <BoundsOctreeTriangle>();
                meshTriangleOctrees[colliderMesh].GetColliding(trianglesInsideProjector, projectorBounds);
                int trianglesInsideProjectorCount = trianglesInsideProjector.Count;

                // optimization: ensure the decal mesh list capacities are large enough to contain all
                // of the triangles. By themselves the lists would reallocate their array many times.
                if (vertices.Capacity < trianglesInsideProjectorCount)
                {
                    vertices.Capacity  = trianglesInsideProjectorCount;
                    triangles.Capacity = trianglesInsideProjectorCount;
                    uvs.Capacity       = trianglesInsideProjectorCount;
                }

                // iterate over all triangles inside of the projector bounds:
                for (int i = 0; i < trianglesInsideProjectorCount; i++)
                {
                    // fetch a triangle from the octree.
                    BoundsOctreeTriangle triangle = trianglesInsideProjector[i];

                    // the mesh vertices are in world space 1:1 to how they appear in the scene.

                    // if the triangle exceeds the maximum angle we discard it.
                    if (Vector3.Dot(transform.forward, triangle.normal) >= maxAngleCos)
                    {
                        continue;
                    }

                    // optimization?: if the triangle is wholly inside of the projector we don't have to clip it.

                    // clip the triangle to fit inside of the projector box.
                    poly[0]   = triangle.vertex1;
                    poly[1]   = triangle.vertex2;
                    poly[2]   = triangle.vertex3;
                    polyCount = clipping.ClipTriangle(poly);

                    if (polyCount >= 3)
                    {
                        Vector3[] triangulated;
                        int       triangulatedCount;

                        // only triangulate if required:
                        if (polyCount > 3)
                        {
                            triangulated      = Triangulate(poly, polyCount);
                            triangulatedCount = triangulated.Length;
                        }
                        else
                        {
                            triangulated      = poly;
                            triangulatedCount = 3;
                        }

                        for (int tr = 0; tr < triangulatedCount; tr += 3)
                        {
                            Vector3 colliderVertex1 = triangulated[tr + 0];
                            Vector3 colliderVertex2 = triangulated[tr + 1];
                            Vector3 colliderVertex3 = triangulated[tr + 2];

                            // use the horizontal and vertical plane through the projector box.
                            // the distance of the vertices to the planes are used to calculate UV coordinates.
                            Vector2 uv1 = new Vector2((vplane.GetDistanceToPoint(colliderVertex1) * uscale) + uoffset, (hplane.GetDistanceToPoint(colliderVertex1) * vscale) + voffset);
                            Vector2 uv2 = new Vector2((vplane.GetDistanceToPoint(colliderVertex2) * uscale) + uoffset, (hplane.GetDistanceToPoint(colliderVertex2) * vscale) + voffset);
                            Vector2 uv3 = new Vector2((vplane.GetDistanceToPoint(colliderVertex3) * uscale) + uoffset, (hplane.GetDistanceToPoint(colliderVertex3) * vscale) + voffset);

                            // calculate the z-offset.
                            Vector3 normal = triangle.normal * zOffsetMultiplier;

                            // undo our transformation so that the mesh looks correct in the scene.
                            colliderVertex1 = transform.InverseTransformPoint(colliderVertex1 + normal);
                            colliderVertex2 = transform.InverseTransformPoint(colliderVertex2 + normal);
                            colliderVertex3 = transform.InverseTransformPoint(colliderVertex3 + normal);

                            // add vertices to the decal mesh.
                            vertices.Add(colliderVertex1); triangles.Add(vertices.Count - 1); uvs.Add(uv1);
                            vertices.Add(colliderVertex2); triangles.Add(vertices.Count - 1); uvs.Add(uv2);
                            vertices.Add(colliderVertex3); triangles.Add(vertices.Count - 1); uvs.Add(uv3);
                        }
                    }
                }
            }

            if (vertices.Count > 0)
            {
                mesh.SetVertices(vertices);
                mesh.SetTriangles(triangles, 0);
                mesh.SetUVs(0, uvs);
                mesh.RecalculateNormals(meshUpdateFlags);
                mesh.RecalculateTangents(meshUpdateFlags);
            }
        }
Пример #24
0
 [NativeThrows] static extern void ApplyToMeshImpl([NotNull] Mesh mesh, IntPtr data, MeshUpdateFlags flags);
Пример #25
0
    //struct PtrStruct { public IntPtr m_Ptr; }

    public static unsafe void ApplyAndDisposeWritableMeshData(this Mesh.MeshDataArray @this, Mesh[] meshes, int realLength, MeshUpdateFlags flags = MeshUpdateFlags.Default)
    {
        if (meshes == null)
        {
            throw new ArgumentNullException(nameof(meshes), "Mesh list is null");
        }
        if (@this.Length < realLength)
        {
            throw new InvalidOperationException($"{nameof(Mesh.MeshDataArray)} length ({@this.Length}) cannot be less than destination meshes length ({realLength})");
        }
        if (meshes.Length < realLength)
        {
            throw new InvalidOperationException($"{nameof(meshes)} length ({meshes.Length}) cannot be less than destination meshes length ({realLength})");
        }
        if (realLength == 0)
        {
            @this.Dispose();
            return;
        }

        for (int i = 0; i < realLength; ++i)
        {
            Mesh m = meshes[i];
            if (m == null)
            {
                throw new ArgumentNullException(nameof(meshes), $"Mesh at index {i} is null");
            }
        }

        // UNTESTED
        var ptrs = (IntPtr *)UnsafeUtility.AddressOf(ref @this); // First value of Mesh.MeshDataArray should be IntPtr*

        /*
         * var ptrs = stackalloc IntPtr[realLength];
         * for (int i = 0; i < realLength; i++)
         * {
         *  var meshData = @this[i];
         *  //ptrs[i] = ((PtrStruct*)&meshData)->m_Ptr;
         *  ptrs[i] = *((IntPtr*)&meshData);
         * }*/

        ApplyToMeshesImpl(meshes, ptrs, realLength, flags);
        @this.Dispose();
    }