/// <summary> /// Initializes all the stuff related to the mesh. /// </summary> private void Init() { DisposeNativeDatastructures(); AllocateNativeDatastructures(); ResetMesh(); new SetupIndicesJob { indices = indices, resolution = resolution, } .ScheduleParallel(GetNumQuads(), 64, default(JobHandle)) .Complete(); VertexAttributeDescriptor vertexDesc = new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, 0); mesh.SetVertexBufferParams(vertices.Length, vertexDesc); mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt16); mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length, 0, MeshUpdateFlags.Default); mesh.SetIndexBufferData(indices, 0, 0, indices.Length, MeshUpdateFlags.Default); SubMeshDescriptor submeshDesc = new SubMeshDescriptor(0, indices.Length, MeshTopology.Triangles); mesh.SetSubMesh(0, submeshDesc, MeshUpdateFlags.Default); mesh.bounds = new Bounds(Vector3.zero, Vector3.one * 1000.0f); }
private static void SetDataToMesh(UnityEngine.Mesh mesh, MyMeshData meshData, NativeArray <TurtleMeshAllocationCounter> submeshSizes) { UnityEngine.Profiling.Profiler.BeginSample("applying mesh data"); int vertexCount = meshData.vertexData.Length; int indexCount = meshData.indices.Length; mesh.Clear(); mesh.SetVertexBufferParams(vertexCount, GetVertexLayout()); mesh.SetVertexBufferData(meshData.vertexData, 0, 0, vertexCount, 0, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontValidateIndices); mesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); mesh.SetIndexBufferData(meshData.indices, 0, 0, indexCount, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontValidateIndices); mesh.subMeshCount = submeshSizes.Length; for (int i = 0; i < submeshSizes.Length; i++) { var submeshSize = submeshSizes[i]; var descriptor = new SubMeshDescriptor() { baseVertex = 0, topology = MeshTopology.Triangles, indexCount = submeshSize.totalTriangleIndexes, indexStart = submeshSize.indexInTriangles, }; mesh.SetSubMesh(i, descriptor, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontValidateIndices); } mesh.bounds = meshData.meshBounds[0]; UnityEngine.Profiling.Profiler.EndSample(); }
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; }
private unsafe void UpdateMesh(ImDrawDataPtr drawData, Vector2 fbSize) { int subMeshCount = 0; // nr of submeshes is the same as the nr of ImDrawCmd for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { subMeshCount += drawData.CmdListsRange[n].CmdBuffer.Size; } // set mesh structure if (_prevSubMeshCount != subMeshCount) { _mesh.Clear(true); // occasionally crashes when changing subMeshCount without clearing first _mesh.subMeshCount = _prevSubMeshCount = subMeshCount; } _mesh.SetVertexBufferParams(drawData.TotalVtxCount, s_attributes); _mesh.SetIndexBufferParams(drawData.TotalIdxCount, IndexFormat.UInt16); // upload data into mesh int vtxOf = 0; int idxOf = 0; List <SubMeshDescriptor> descriptors = new List <SubMeshDescriptor>(); for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { ImDrawListPtr drawList = drawData.CmdListsRange[n]; NativeArray <ImDrawVert> vtxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ImDrawVert>( (void *)drawList.VtxBuffer.Data, drawList.VtxBuffer.Size, Allocator.None); NativeArray <ushort> idxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ushort>( (void *)drawList.IdxBuffer.Data, drawList.IdxBuffer.Size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref vtxArray, AtomicSafetyHandle.GetTempMemoryHandle()); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref idxArray, AtomicSafetyHandle.GetTempMemoryHandle()); #endif // upload vertex/index data _mesh.SetVertexBufferData(vtxArray, 0, vtxOf, vtxArray.Length, 0, NoMeshChecks); _mesh.SetIndexBufferData(idxArray, 0, idxOf, idxArray.Length, NoMeshChecks); // define subMeshes for (int i = 0, iMax = drawList.CmdBuffer.Size; i < iMax; ++i) { ImDrawCmdPtr cmd = drawList.CmdBuffer[i]; SubMeshDescriptor descriptor = new SubMeshDescriptor { topology = MeshTopology.Triangles, indexStart = idxOf + (int)cmd.IdxOffset, indexCount = (int)cmd.ElemCount, baseVertex = vtxOf + (int)cmd.VtxOffset, }; descriptors.Add(descriptor); } vtxOf += vtxArray.Length; idxOf += idxArray.Length; } _mesh.SetSubMeshes(descriptors, NoMeshChecks); _mesh.UploadMeshData(false); }
void Update() { _VertexCount = TessellationFactor * TessellationFactor * 6; if (_Mesh == null || _Recalculate) { Release(); _Recalculate = false; _Mesh = new Mesh(); _Mesh.name = "NURBS Surface"; _Mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; _Mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw; VertexAttributeDescriptor[] attributes = new [] { new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, stream: 0), new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3, stream: 0), new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4, stream: 0), new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2, stream: 0), }; _Mesh.SetVertexBufferParams(_VertexCount, attributes); _Mesh.SetIndexBufferParams(_VertexCount, IndexFormat.UInt32); NativeArray <int> indexBuffer = new NativeArray <int>(_VertexCount, Allocator.Temp); for (int i = 0; i < _VertexCount; ++i) { indexBuffer[i] = i; } _Mesh.SetIndexBufferData(indexBuffer, 0, 0, indexBuffer.Length, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices); indexBuffer.Dispose(); SubMeshDescriptor subMeshDescriptor = new SubMeshDescriptor(0, _VertexCount, MeshTopology.Triangles); subMeshDescriptor.bounds = new Bounds(Vector3.zero, new Vector3(1e5f, 1e5f, 1e5f)); _Mesh.SetSubMesh(0, subMeshDescriptor); _Mesh.bounds = subMeshDescriptor.bounds; GetComponent <MeshFilter>().sharedMesh = _Mesh; _GraphicsBuffer = _Mesh.GetVertexBuffer(0); } LoadDefaultCollection(); NurbsSurfaceCS.SetInt("_VertexCount", _VertexCount); NurbsSurfaceCS.SetInt("_TessellationFactor", TessellationFactor); NurbsSurfaceCS.SetBuffer(0, "_GraphicsBuffer", _GraphicsBuffer); NurbsSurfaceCS.SetVectorArray("_ControlPoints", _ControlPoints.ToArray()); NurbsSurfaceCS.GetKernelThreadGroupSizes(0, out uint x, out uint y, out uint z); int threadGroupsX = Mathf.Min((_VertexCount + (int)x - 1) / (int)x, 65535); int threadGroupsY = (int)y; int threadGroupsZ = (int)z; NurbsSurfaceCS.Dispatch(0, threadGroupsX, threadGroupsY, threadGroupsZ); if (Input.GetKeyDown(KeyCode.R)) { LoadDefaultSettings(); } if (Input.GetKeyDown(KeyCode.Space) && (_Mesh != null)) { ExportMesh(); } }
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 }
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); }
public static void Build(NativeSlice <Bullet> bullets, float size, Mesh mesh) { var bulletCount = bullets.Length; var vertexCount = bulletCount * 4; mesh.Clear(); // Vertex/index buffer allocation var varray = new NativeArray <Quad>(bulletCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var iarray = new NativeArray <uint>(vertexCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Vertex/index array construction var vjob = new VertexConstructionJob(bullets, size, varray); var ijob = new IndexConstructionJob(iarray); var handle = vjob.Schedule(bulletCount, 64); handle = ijob.Schedule(vertexCount, 64, handle); handle.Complete(); // Vertex buffer mesh.SetVertexBufferParams (vertexCount, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 2), new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2)); mesh.SetVertexBufferData(varray, 0, 0, bulletCount); // Index buffer mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt32); mesh.SetIndexBufferData(iarray, 0, 0, vertexCount); // Submesh definition var meshDesc = new SubMeshDescriptor(0, vertexCount, MeshTopology.Quads); mesh.SetSubMesh(0, meshDesc, MeshUpdateFlags.DontRecalculateBounds); // Cleanup varray.Dispose(); iarray.Dispose(); }
void Update() { if (_Mesh && _Mesh.vertexCount != TriangleCount * 3) { Release(); } if (_Mesh == null) { _Mesh = new Mesh(); _Mesh.name = "ProceduralGrass"; _Mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; VertexAttributeDescriptor[] attributes = new [] { new VertexAttributeDescriptor(VertexAttribute.Position, stream: 0), new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1), new VertexAttributeDescriptor(VertexAttribute.TexCoord0, stream: 2) }; _Mesh.SetVertexBufferParams(TriangleCount * 3, attributes); _Mesh.SetIndexBufferParams(TriangleCount * 3, IndexFormat.UInt32); NativeArray <int> indexBuffer = new NativeArray <int>(TriangleCount * 3, Allocator.Temp); for (int i = 0; i < TriangleCount * 3; ++i) { indexBuffer[i] = i; } _Mesh.SetIndexBufferData(indexBuffer, 0, 0, indexBuffer.Length, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices); indexBuffer.Dispose(); SubMeshDescriptor submesh = new SubMeshDescriptor(0, TriangleCount * 3, MeshTopology.Triangles); submesh.bounds = new Bounds(Vector3.zero, new Vector3(2000, 2, 2000)); _Mesh.SetSubMesh(0, submesh); _Mesh.bounds = submesh.bounds; GetComponent <MeshFilter>().sharedMesh = _Mesh; _Material = new Material(ProceduralGrassPS); _Material.mainTexture = GrassTexture; GetComponent <MeshRenderer>().sharedMaterial = _Material; } _VertexBuffer ??= _Mesh.GetVertexBuffer(0); _NormalBuffer ??= _Mesh.GetVertexBuffer(1); _TexcoordBuffer ??= _Mesh.GetVertexBuffer(2); ProceduralGrassCS.SetInt("_TriangleCount", TriangleCount); ProceduralGrassCS.SetBuffer(0, "_VertexBuffer", _VertexBuffer); ProceduralGrassCS.SetBuffer(0, "_TexcoordBuffer", _TexcoordBuffer); ProceduralGrassCS.SetBuffer(0, "_NormalBuffer", _NormalBuffer); ProceduralGrassCS.SetFloat("_Time", Time.time); ProceduralGrassCS.Dispatch(0, (TriangleCount + 64 - 1) / 64, 1, 1); }
/// <summary> /// Forces the regeneration of the mesh /// </summary> public void GenerateMeshImmediate(ChunkProperties chunkProperties) { JobHandleWithData <IMesherJob> jobHandleWithData = VoxelWorld.VoxelMesher.CreateMesh(VoxelWorld.VoxelDataStore, VoxelWorld.VoxelColorStore, chunkProperties.ChunkCoordinate); if (jobHandleWithData == null) { return; } IMesherJob job = jobHandleWithData.JobData; Mesh mesh = new Mesh(); SubMeshDescriptor subMesh = new SubMeshDescriptor(0, 0); jobHandleWithData.JobHandle.Complete(); int vertexCount = job.VertexCountCounter.Count * 3; job.VertexCountCounter.Dispose(); mesh.SetVertexBufferParams(vertexCount, MeshingVertexData.VertexBufferMemoryLayout); mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt16); mesh.SetVertexBufferData(job.OutputVertices, 0, 0, vertexCount, 0, MeshUpdateFlags.DontValidateIndices); mesh.SetIndexBufferData(job.OutputTriangles, 0, 0, vertexCount, MeshUpdateFlags.DontValidateIndices); job.OutputVertices.Dispose(); job.OutputTriangles.Dispose(); mesh.subMeshCount = 1; subMesh.indexCount = vertexCount; mesh.SetSubMesh(0, subMesh); mesh.RecalculateBounds(); chunkProperties.MeshFilter.sharedMesh = mesh; chunkProperties.MeshCollider.sharedMesh = mesh; chunkProperties.MeshCollider.enabled = true; chunkProperties.MeshRenderer.enabled = true; chunkProperties.HasChanges = false; chunkProperties.IsMeshGenerated = true; }
void Awake() { // Create vertices. _vertices = new Vertex[] { new Vertex() { position = Quaternion.AngleAxis(0 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, normal = Vector3.back }, new Vertex() { position = Quaternion.AngleAxis(2 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, normal = Vector3.back }, new Vertex() { position = Quaternion.AngleAxis(1 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, normal = Vector3.back }, }; // Create mesh and markt it dynamic, to tell Unity that we will update the verticies continously. _mesh = new Mesh(); _mesh.MarkDynamic(); // Set the index parameters. UInt16 will allow 65535 indices. If you need more, use UInt32. _mesh.SetIndexBufferParams(3, IndexFormat.UInt16); // Set the vertex parameters (the data layout for a one vertex). For the yellow triangle, we just need positions. VertexAttributeDescriptor[] vertexDataLayout = new VertexAttributeDescriptor[] { new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3), new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3) }; _mesh.SetVertexBufferParams(3, vertexDataLayout); // Set the sub mesh descriptor. SubMeshDescriptor meshDescriptor = new SubMeshDescriptor(0, 3, MeshTopology.Triangles); _mesh.SetSubMesh(0, meshDescriptor, meshFlags); // Set bounds. If you vertices move a lot, you may want to change this in Update. _mesh.bounds = new Bounds(Vector3.zero, Vector3.one); // Set initial mesh data. _mesh.SetVertexBufferData(_vertices, 0, 0, _vertices.Length, 0, meshFlags); _mesh.SetIndexBufferData(new ushort[] { 0, 1, 2 }, 0, 0, 3, meshFlags); }
void Update() { _VertexCount = TessellationFactor * TessellationFactor * _Attributes.Length; if (_Mesh == null || _Recalculate) { _Recalculate = false; Release(); _Mesh = new Mesh(); _Mesh.name = _Name; _Mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; _Mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw; VertexAttributeDescriptor[] attributes = new [] { new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, stream: 0), new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3, stream: 0), new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2, stream: 0), }; _Mesh.SetVertexBufferParams(_VertexCount, attributes); _Mesh.SetIndexBufferParams(_VertexCount, IndexFormat.UInt32); NativeArray <int> indexBuffer = new NativeArray <int>(_VertexCount, Allocator.Temp); for (int i = 0; i < _VertexCount; ++i) { indexBuffer[i] = i; } _Mesh.SetIndexBufferData(indexBuffer, 0, 0, indexBuffer.Length, MeshUpdateFlags.DontRecalculateBounds); indexBuffer.Dispose(); SubMeshDescriptor submesh = new SubMeshDescriptor(0, _VertexCount, MeshTopology.Triangles); submesh.bounds = _Bounds; _Mesh.SetSubMesh(0, submesh); _Mesh.bounds = submesh.bounds; GetComponent <MeshFilter>().sharedMesh = _Mesh; _GraphicsBuffer = _Mesh.GetVertexBuffer(0); PhongTessellationCS.SetInt("_VertexCount", _VertexCount); PhongTessellationCS.SetInt("_TessellationFactor", TessellationFactor); PhongTessellationCS.SetFloat("_Phong", Phong); PhongTessellationCS.SetBuffer(0, "_GraphicsBuffer", _GraphicsBuffer); PhongTessellationCS.SetBuffer(0, "_ComputeBuffer", _ComputeBuffer); PhongTessellationCS.GetKernelThreadGroupSizes(0, out uint x, out uint y, out uint z); int threadGroupsX = Mathf.Min((_VertexCount + (int)x - 1) / (int)x, 65535); int threadGroupsY = (int)y; int threadGroupsZ = (int)z; PhongTessellationCS.Dispatch(0, threadGroupsX, threadGroupsY, threadGroupsZ); } }
void Awake() { // Create vertices. _vertices = new Vector3[] { Quaternion.AngleAxis(0 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, Quaternion.AngleAxis(2 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, Quaternion.AngleAxis(1 / 3f * 360, Vector3.forward) * Vector3.up * 0.5f, }; // Create mesh and markt it dynamic, to tell Unity that we will update the verticies continously. _mesh = new Mesh(); _mesh.MarkDynamic(); // Set the index parameters. UInt16 will allow 65535 indices. If you need more, use UInt32. _mesh.SetIndexBufferParams(3, IndexFormat.UInt16); // Set the vertex parameters (the data layout for a one vertex). For the yellow triangle, we just need positions. VertexAttributeDescriptor[] vertexDataLayout = new VertexAttributeDescriptor[] { new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3) }; _mesh.SetVertexBufferParams(3, vertexDataLayout); // Set the sub mesh descriptor. SubMeshDescriptor meshDescriptor = new SubMeshDescriptor(0, 3, MeshTopology.Triangles); _mesh.SetSubMesh(0, meshDescriptor, meshFlags); // Set bounds. If you vertices move a lot, you may want to change this in Update. _mesh.bounds = new Bounds(Vector3.zero, Vector3.one); // Set indices. _mesh.SetIndexBufferData(new ushort[] { 0, 1, 2 }, 0, 0, 3, meshFlags); // Create material (from shader located in Resources folder). Material material = new Material(Shader.Find("Hidden/" + nameof(MeshDemo))); // Create necessary components and set references. MeshFilter filter = gameObject.AddComponent <MeshFilter>(); MeshRenderer render = gameObject.AddComponent <MeshRenderer>(); filter.sharedMesh = _mesh; render.material = material; }
public void SetMeshData(int vertexCount, NativeArray <VertexData> vertices, NativeArray <ushort> triangles) { Mesh mesh = new Mesh(); SubMeshDescriptor subMesh = new SubMeshDescriptor(); mesh.SetVertexBufferParams(vertexCount, VertexData.bufferMemoryLayout); mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt16); mesh.SetVertexBufferData(vertices, 0, 0, vertexCount, 0, MeshUpdateFlags.DontValidateIndices); mesh.SetIndexBufferData(triangles, 0, 0, vertexCount, MeshUpdateFlags.DontValidateIndices); mesh.subMeshCount = 1; subMesh.indexCount = vertexCount; mesh.SetSubMesh(0, subMesh); mesh.RecalculateBounds(); this.meshFilter.mesh = mesh; this.meshCollider.sharedMesh = mesh; }
static Mesh CreateQuadMesh() { Mesh mesh = new Mesh(); mesh.hideFlags = HideFlags.HideAndDontSave; // Verticies. VertexAttributeDescriptor[] vertexDataLayout = new VertexAttributeDescriptor[] { new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 2) }; mesh.SetVertexBufferParams(4, vertexDataLayout); mesh.SetVertexBufferData( new Vector2[] { new Vector2(-1, -1), new Vector2(-1, 1), new Vector2(1, 1), new Vector2(1, -1), }, 0, 0, 4, 0, meshFlags ); // Indices. mesh.SetIndexBufferParams(4, IndexFormat.UInt16); mesh.SetIndexBufferData(new ushort[] { 0, 1, 2, 3 }, 0, 0, 4, meshFlags); // Sub mesh. SubMeshDescriptor meshDescriptor = new SubMeshDescriptor(0, 4, MeshTopology.Quads); meshDescriptor.bounds = new Bounds(Vector3.zero, Vector3.one * 2); meshDescriptor.vertexCount = 4; mesh.subMeshCount = 1; mesh.SetSubMesh(0, meshDescriptor, meshFlags); // Bounds. mesh.bounds = meshDescriptor.bounds; mesh.UploadMeshData(true); return(mesh); }
public void FillMesh(int vertexCount, int indexCount, NativeArray <Vector3> vertices, NativeArray <int> triangles, Bounds bounds, VertexAttributeDescriptor[] meshVertexLayout) { mesh.SetVertexBufferParams(vertexCount, meshVertexLayout); mesh.SetVertexBufferData(vertices, 0, 0, vertexCount, 0); mesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); mesh.SetIndexBufferData(triangles, 0, 0, vertexCount); var descriptor = new SubMeshDescriptor { topology = MeshTopology.Triangles, indexCount = indexCount }; mesh.SetSubMesh(0, descriptor); mesh.bounds = bounds; mesh.RecalculateNormals(); if (HasCollider) { meshCollider.enabled = false; meshCollider.enabled = true; } }
void UpdateMesh(NativeSlice <float> source) { if (_mesh == null) { _mesh = new Mesh(); _mesh.bounds = new Bounds(Vector3.zero, Vector3.one * 10); // Initial vertices using (var vertices = CreateVertexArray(source)) { var pos = new VertexAttributeDescriptor (VertexAttribute.Position, VertexAttributeFormat.Float32, 3); _mesh.SetVertexBufferParams(vertices.Length, pos); _mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length); } // Initial indices using (var indices = CreateIndexArray()) { _mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt32); _mesh.SetIndexBufferData(indices, 0, 0, indices.Length); var lines = new SubMeshDescriptor (0, indices.Length, MeshTopology.LineStrip); _mesh.SetSubMesh(0, lines); } } else { // Vertex update using (var vertices = CreateVertexArray(source)) _mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length); } }
private static void DecomposeMesh(Mesh mesh, int subMeshIndex, out SourceVertex[] vertices, out int[] indices) { SubMeshDescriptor subMeshDescriptor = mesh.GetSubMesh(subMeshIndex); Vector3[] meshVertices = mesh.vertices; Vector2[] meshUVs = mesh.uv; int[] meshIndices = mesh.triangles; vertices = new SourceVertex[subMeshDescriptor.vertexCount]; indices = new int[subMeshDescriptor.indexCount]; for (int i = 0; i < mesh.vertexCount; ++i) { int wholeMeshIndex = i + subMeshDescriptor.firstVertex; vertices[i] = new SourceVertex { position = meshVertices[wholeMeshIndex], uv = meshUVs[wholeMeshIndex] }; } for (int i = 0; i < subMeshDescriptor.indexCount; ++i) { indices[i] = meshIndices[i + subMeshDescriptor.indexStart] + subMeshDescriptor.baseVertex - subMeshDescriptor.firstVertex; } }
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); }
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); }
public override Primitive?CreatePrimitive() { Profiler.BeginSample("CreatePrimitive"); jobHandle.Complete(); var msh = new UnityEngine.Mesh(); msh.name = mesh.name; vertexData.ApplyOnMesh(msh, defaultMeshUpdateFlags); Profiler.BeginSample("SetIndices"); int indexCount = 0; var allBounds = vertexData.bounds; 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, defaultMeshUpdateFlags); Profiler.EndSample(); Profiler.BeginSample("SetSubMesh"); var subMeshDescriptor = new SubMeshDescriptor { indexStart = indexCount, indexCount = indices[i].Length, topology = topology, baseVertex = 0, firstVertex = 0, vertexCount = vertexData.vertexCount }; if (allBounds.HasValue) { // Setting the submeshes' bounds to the overall bounds // Calculating the actual sub-mesh bounds (by iterating the verts referenced // by the sub-mesh indices) would be slow. Also, hardly any glTFs re-use // the same vertex buffer across primitives of a node (which is the // only way a mesh can have sub-meshes) subMeshDescriptor.bounds = allBounds.Value; } msh.SetSubMesh(i, subMeshDescriptor, defaultMeshUpdateFlags); 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(); } if (allBounds.HasValue) { msh.bounds = allBounds.Value; } else { Profiler.BeginSample("RecalculateBounds"); #if DEBUG Debug.LogError("Bounds have to be recalculated (slow operation). Check if position accessors have proper min/max values"); #endif msh.RecalculateBounds(); 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)); }
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); }
public void SetSubMesh(int index, SubMeshDescriptor desc, MeshUpdateFlags flags = MeshUpdateFlags.Default) { CheckWriteAccess(); SetSubMeshImpl(m_Ptr, index, desc, flags); }
public void CombineMesh(ChunkMeshData chunkMeshData) { //获取输出meshData Mesh.MeshDataArray outMeshDataArray = Mesh.AllocateWritableMeshData(1); Mesh.MeshData outMesh = outMeshDataArray[0]; Mesh.MeshDataArray outMeshDataArrayCollider = Mesh.AllocateWritableMeshData(1); Mesh.MeshData outMeshCollider = outMeshDataArrayCollider[0]; Mesh.MeshDataArray outMeshDataArrayTrigger = Mesh.AllocateWritableMeshData(1); Mesh.MeshData outMeshTrigger = outMeshDataArrayTrigger[0]; int subMeshCount = 0; int subMeshIndexCount = 0; List <int> trisDataAll = new List <int>(); List <SubMeshDescriptor> listSubMeshDescriptor = new List <SubMeshDescriptor>(); for (int i = 0; i < chunkMeshData.dicTris.Length; i++) { List <int> trisData = chunkMeshData.dicTris[i]; if (trisData.IsNull()) { continue; } trisDataAll.AddRange(trisData); SubMeshDescriptor subMeshDesc = new SubMeshDescriptor { indexStart = subMeshIndexCount, indexCount = trisData.Count }; listSubMeshDescriptor.Add(subMeshDesc); subMeshCount++; subMeshIndexCount += trisData.Count; } VertexStruct[] listVertex = chunkMeshData.GetVertexStruct(); outMesh.SetVertexBufferParams(listVertex.Length, vertexAttributeDescriptors); VertexStruct[] listVertexCollider = chunkMeshData.GetVertexStructCollider(); outMeshCollider.SetVertexBufferParams(listVertexCollider.Length, vertexAttributeDescriptors); VertexStruct[] listVertexTrigger = chunkMeshData.GetVertexStructTrigger(); outMeshTrigger.SetVertexBufferParams(listVertexTrigger.Length, vertexAttributeDescriptors); //获取点信息 NativeArray <VertexStruct> vertexData = outMesh.GetVertexData <VertexStruct>(); NativeArray <VertexStruct> vertexDataCollider = outMeshCollider.GetVertexData <VertexStruct>(); NativeArray <VertexStruct> vertexDataTrigger = outMeshTrigger.GetVertexData <VertexStruct>(); //设置点信息 NativeArray <VertexStruct> .Copy(listVertex, vertexData); NativeArray <VertexStruct> .Copy(listVertexCollider, vertexDataCollider); NativeArray <VertexStruct> .Copy(listVertexTrigger, vertexDataTrigger); //设置三角数量 outMesh.SetIndexBufferParams(trisDataAll.Count, IndexFormat.UInt32); outMeshCollider.SetIndexBufferParams(chunkMeshData.trisCollider.Count, IndexFormat.UInt32); outMeshTrigger.SetIndexBufferParams(chunkMeshData.trisTrigger.Count, IndexFormat.UInt32); //获取三角下标 NativeArray <int> triangelData = outMesh.GetIndexData <int>(); NativeArray <int> triangelDataCollider = outMeshCollider.GetIndexData <int>(); NativeArray <int> triangelDataTrigger = outMeshTrigger.GetIndexData <int>(); NativeArray <int> .Copy(trisDataAll.ToArray(), triangelData); NativeArray <int> .Copy(chunkMeshData.trisCollider.ToArray(), triangelDataCollider); NativeArray <int> .Copy(chunkMeshData.trisTrigger.ToArray(), triangelDataTrigger); outMesh.subMeshCount = subMeshCount; outMeshCollider.subMeshCount = 1; outMeshTrigger.subMeshCount = 1; for (int i = 0; i < listSubMeshDescriptor.Count; i++) { outMesh.SetSubMesh(i, listSubMeshDescriptor[i]); } outMeshCollider.SetSubMesh(0, new SubMeshDescriptor { indexStart = 0, indexCount = chunkMeshData.trisCollider.Count }); outMeshTrigger.SetSubMesh(0, new SubMeshDescriptor { indexStart = 0, indexCount = chunkMeshData.trisTrigger.Count }); Mesh.ApplyAndDisposeWritableMeshData(outMeshDataArray, chunkMesh); Mesh.ApplyAndDisposeWritableMeshData(outMeshDataArrayCollider, chunkMeshCollider); Mesh.ApplyAndDisposeWritableMeshData(outMeshDataArrayTrigger, chunkMeshTrigger); chunkMesh.RecalculateNormals(); chunkMesh.RecalculateBounds(); //chunkMeshCollider.RecalculateNormals(); //chunkMeshCollider.RecalculateBounds(); //chunkMeshTrigger.RecalculateNormals(); //chunkMeshTrigger.RecalculateBounds(); vertexData.Dispose(); triangelData.Dispose(); vertexDataCollider.Dispose(); triangelDataCollider.Dispose(); vertexDataTrigger.Dispose(); triangelDataTrigger.Dispose(); }
// 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); } }
private void GenerateMesh(PCTrail trail) { trail.Mesh.Clear(false); float3 camForward = Camera.main != null ?(float3)Camera.main.transform.forward : float3(0, 0, 1); if (TrailData.UseForwardOverride) { camForward = normalize(TrailData.ForwardOverride); } trail.activePointCount = NumberOfActivePoints(trail); if (trail.activePointCount < 2) { return; } Profiler.BeginSample("generameshTest"); int vertIndex = 0; for (int i = 0; i < trail.Points.Count; i++) { PCTrailPoint p = trail.Points[i]; float timeAlong = p.TimeActive() / TrailData.Lifetime; if (p.TimeActive() > TrailData.Lifetime) { continue; } if (TrailData.UseForwardOverride && TrailData.ForwardOverrideRelative) { camForward = p.Forward; } float3 Cross = float3.zero; if (i < trail.Points.Count - 1) { Cross = cross(normalize(trail.Points[i + 1].Position - p.Position), camForward); } else { Cross = cross(normalize(p.Position - trail.Points[i - 1].Position), camForward); } Cross = normalize(Cross); //yuck! lets move these into their own functions some time Color c = TrailData.StretchColorToFit ? (TrailData.UsingSimpleColor ? Color.Lerp(TrailData.SimpleColorOverLifeStart, TrailData.SimpleColorOverLifeEnd, 1 - ((float)vertIndex / (float)trail.activePointCount / 2f)) : TrailData.ColorOverLife.Evaluate(1 - ((float)vertIndex / (float)trail.activePointCount / 2f))) : (TrailData.UsingSimpleColor ? Color.Lerp(TrailData.SimpleColorOverLifeStart, TrailData.SimpleColorOverLifeEnd, timeAlong) : TrailData.ColorOverLife.Evaluate(timeAlong)); float s = TrailData.StretchSizeToFit ? (TrailData.UsingSimpleSize ? Mathf.Lerp(TrailData.SimpleSizeOverLifeStart, TrailData.SimpleSizeOverLifeEnd, 1 - ((float)vertIndex / (float)trail.activePointCount / 2f)) : TrailData.SizeOverLife.Evaluate(1 - ((float)vertIndex / (float)trail.activePointCount / 2f))) : (TrailData.UsingSimpleSize ? Mathf.Lerp(TrailData.SimpleSizeOverLifeStart, TrailData.SimpleSizeOverLifeEnd, timeAlong) : TrailData.SizeOverLife.Evaluate(timeAlong)); trail.vertexDatas[vertIndex].verticies = p.Position + Cross * s; trail.vertexDatas[vertIndex].normals = camForward; if (TrailData.MaterialTileLength <= 0) { trail.vertexDatas[vertIndex].uvs = new float2((float)vertIndex / (float)trail.activePointCount / 2f, 0); } else { trail.vertexDatas[vertIndex].uvs = new float2(p.GetDistanceFromStart() / TrailData.MaterialTileLength, 0); } trail.vertexDatas[vertIndex].colors = c; vertIndex++; trail.vertexDatas[vertIndex].verticies = p.Position - Cross * s; trail.vertexDatas[vertIndex].normals = camForward; if (TrailData.MaterialTileLength <= 0) { trail.vertexDatas[vertIndex].uvs = new float2((float)vertIndex / (float)trail.activePointCount / 2f, 1); } else { trail.vertexDatas[vertIndex].uvs = new float2(p.GetDistanceFromStart() / TrailData.MaterialTileLength, 1); } trail.vertexDatas[vertIndex].colors = c; vertIndex++; } float3 finalPosition = trail.vertexDatas[vertIndex - 1].verticies; for (int i = vertIndex; i < trail.vertexDatas.Length; i++) { trail.vertexDatas[i].verticies = finalPosition; } int indIndex = 0; for (int pointIndex = 0; pointIndex < 2 * (trail.activePointCount - 1); pointIndex++) { if (pointIndex % 2 == 0) { trail.indicies[indIndex] = pointIndex; indIndex++; trail.indicies[indIndex] = pointIndex + 1; indIndex++; trail.indicies[indIndex] = pointIndex + 2; } else { trail.indicies[indIndex] = pointIndex + 2; indIndex++; trail.indicies[indIndex] = pointIndex + 1; indIndex++; trail.indicies[indIndex] = pointIndex; } indIndex++; } Profiler.EndSample(); Profiler.BeginSample("SetMeshVertexTest"); trail.Mesh.SetVertexBufferParams(trail.vertexDatas.Length, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3), new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3), new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UNorm8, 4), new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2)); trail.Mesh.SetVertexBufferData(trail.vertexDatas, 0, 0, trail.vertexDatas.Length); trail.Mesh.SetIndexBufferParams(trail.indicies.Length, IndexFormat.UInt32); trail.Mesh.SetIndexBufferData(trail.indicies, 0, 0, trail.indicies.Length); trail.Mesh.subMeshCount = 1; var subMeshDescriptor = new SubMeshDescriptor(0, trail.indicies.Length, MeshTopology.Triangles); trail.Mesh.SetSubMesh(0, subMeshDescriptor); Profiler.EndSample(); }
extern public void SetSubMesh(int index, SubMeshDescriptor desc);
extern public void SetSubMesh(int index, SubMeshDescriptor desc, UnityEngine.Rendering.MeshUpdateFlags flags = UnityEngine.Rendering.MeshUpdateFlags.Default);
[NativeMethod(IsThreadSafe = true, ThrowsException = true)] static extern void SetSubMeshImpl(IntPtr self, int index, SubMeshDescriptor desc, MeshUpdateFlags flags);
public static void CreateMesh_MeshDataApi() { var sw = Stopwatch.StartNew(); // Find all MeshFilter objects in the scene smp1.Begin(); var meshFilters = FindObjectsOfType <MeshFilter>(); smp1.End(); // Need to figure out how large the output mesh needs to be (in terms of vertex/index count), // as well as get transforms and vertex/index location offsets for each mesh. smp2.Begin(); var jobs = new ProcessMeshDataJob(); jobs.CreateInputArrays(meshFilters.Length); var inputMeshes = new List <Mesh>(meshFilters.Length); var vertexStart = 0; var indexStart = 0; var meshCount = 0; for (var i = 0; i < meshFilters.Length; ++i) { var mf = meshFilters[i]; var go = mf.gameObject; if (go.CompareTag("EditorOnly")) { DestroyImmediate(go); continue; } var mesh = mf.sharedMesh; inputMeshes.Add(mesh); jobs.vertexStart[meshCount] = vertexStart; jobs.indexStart[meshCount] = indexStart; jobs.xform[meshCount] = go.transform.localToWorldMatrix; vertexStart += mesh.vertexCount; indexStart += (int)mesh.GetIndexCount(0); jobs.bounds[meshCount] = new float3x2(new float3(Mathf.Infinity), new float3(Mathf.NegativeInfinity)); ++meshCount; } smp2.End(); // Acquire read-only data for input meshes jobs.meshData = Mesh.AcquireReadOnlyMeshData(inputMeshes); // Create and initialize writable data for the output mesh var outputMeshData = Mesh.AllocateWritableMeshData(1); jobs.outputMesh = outputMeshData[0]; jobs.outputMesh.SetIndexBufferParams(indexStart, IndexFormat.UInt32); jobs.outputMesh.SetVertexBufferParams(vertexStart, new VertexAttributeDescriptor(VertexAttribute.Position), new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1)); // Launch mesh processing jobs var handle = jobs.Schedule(meshCount, 4); // Create destination Mesh object smp3.Begin(); var newMesh = new Mesh(); newMesh.name = "CombinedMesh"; var sm = new SubMeshDescriptor(0, indexStart, MeshTopology.Triangles); sm.firstVertex = 0; sm.vertexCount = vertexStart; // Wait for jobs to finish, since we'll have to access the produced mesh/bounds data at this point handle.Complete(); // Final bounding box of the whole mesh is union of the bounds of individual transformed meshes var bounds = new float3x2(new float3(Mathf.Infinity), new float3(Mathf.NegativeInfinity)); for (var i = 0; i < meshCount; ++i) { var b = jobs.bounds[i]; bounds.c0 = math.min(bounds.c0, b.c0); bounds.c1 = math.max(bounds.c1, b.c1); } sm.bounds = new Bounds((bounds.c0 + bounds.c1) * 0.5f, bounds.c1 - bounds.c0); jobs.outputMesh.subMeshCount = 1; jobs.outputMesh.SetSubMesh(0, sm, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontNotifyMeshUsers); Mesh.ApplyAndDisposeWritableMeshData(outputMeshData, new[] { newMesh }, MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontNotifyMeshUsers); newMesh.bounds = sm.bounds; smp3.End(); // Dispose of the read-only mesh data and temporary bounds array smp4.Begin(); jobs.meshData.Dispose(); jobs.bounds.Dispose(); smp4.End(); // Create new GameObject with the new mesh var newGo = new GameObject("CombinedMesh", typeof(MeshFilter), typeof(MeshRenderer)); newGo.tag = "EditorOnly"; var newMf = newGo.GetComponent <MeshFilter>(); var newMr = newGo.GetComponent <MeshRenderer>(); newMr.material = AssetDatabase.LoadAssetAtPath <Material>("Assets/CreateMeshFromAllSceneMeshes/MaterialForNewlyCreatedMesh.mat"); newMf.sharedMesh = newMesh; //newMesh.RecalculateNormals(); // faster to do normal xform in the job var dur = sw.ElapsedMilliseconds; Debug.Log($"Took {dur/1000.0:F2}sec for {meshCount} objects, total {vertexStart} verts"); Selection.activeObject = newGo; }