public MetalKitEssentialsMesh(MTKMesh mtkMesh, MDLMesh mdlMesh, IMTLDevice device)
        {
            mesh = mtkMesh;
            submeshes = new List<MetalKitEssentialsSubmesh> ();

            if ((nuint)mtkMesh.Submeshes.Length != mdlMesh.Submeshes.Count)
                throw new Exception ("Number od submeshes should be equal");

            for (int i = 0; i < mtkMesh.Submeshes.Length; i++) {
                // Create our own app specifc submesh to hold the MetalKit submesh.
                var submesh = new MetalKitEssentialsSubmesh (mtkMesh.Submeshes[i], mdlMesh.Submeshes.GetItem <MDLSubmesh>((nuint)i), device);
                submeshes.Add (submesh);
            }
        }
Exemple #2
0
        public void CreateBoxWithDimensonTest()
        {
            Vector3  V3  = new Vector3(1, 2, 3);
            Vector3i V3i = new Vector3i(4, 5, 6);

            using (var obj = MDLMesh.CreateBox(V3, V3i, MDLGeometryType.Triangles, true, null)) {
                Assert.IsNotNull(obj, "obj");
                Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                    MaxBounds = new Vector3(0.5f, 1, 1.5f), MinBounds = new Vector3(-0.5f, -1, -1.5f)
                }, obj.BoundingBox, "BoundingBox");
                Assert.AreEqual((nuint)1, obj.Submeshes.Count, "Submeshes Count");
                Assert.AreEqual(1, obj.VertexBuffers.Length, "VertexBuffers Count");
                Assert.AreEqual(TestRuntime.CheckXcodeVersion(7, 3) ? (nuint)214 : (nuint)24, obj.VertexCount, "VertexCount");
                Assert.AreEqual((nuint)31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual((nuint)31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #3
0
        public void CreateCylindroidTest()
        {
            var V2 = new Vector2(1, 1);

            using (var obj = MDLMesh.CreateCylindroid(1, V2, 3, 1, MDLGeometryType.Triangles, true, null)) {
                Assert.IsNotNull(obj, "obj");
#if MONOMAC
                if (TestRuntime.CheckSystemVersion(ApplePlatform.MacOSX, 10, 12))
                {
                    Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                        MaxBounds = new Vector3(0.866025448f, 0.5f, 1f), MinBounds = new Vector3(-0.866025388f, -0.5f, -0.5f)
                    }, obj.BoundingBox, "BoundingBox");
                }
                else
                {
                    Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                        MaxBounds = new Vector3(1f, 0.5f, 1f), MinBounds = new Vector3(-0.866025388f, -0.5f, -0.866025388f)
                    }, obj.BoundingBox, "BoundingBox");
                }
#else
                if (TestRuntime.CheckXcodeVersion(8, 2))
                {
                    Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                        MaxBounds = new Vector3(0.866025448f, 0.5f, 1f), MinBounds = new Vector3(-0.866025388f, -0.5f, -0.5f)
                    }, obj.BoundingBox, "BoundingBox");
                }
                else if (TestRuntime.CheckXcodeVersion(8, 0))
                {
                    Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                        MaxBounds = new Vector3(0.866025448f, 1.0f, 1f), MinBounds = new Vector3(-0.866025388f, -1.0f, -0.5f)
                    }, obj.BoundingBox, "BoundingBox");
                }
                else
                {
                    Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                        MaxBounds = new Vector3(1f, 0.5f, 1f), MinBounds = new Vector3(-0.866025388f, -0.5f, -0.866025388f)
                    }, obj.BoundingBox, "BoundingBox");
                }
#endif
                Assert.That(obj.VertexBuffers.Length, Is.GreaterThanOrEqualTo(1), "VertexBuffers Count");
                Assert.AreEqual((nuint)1, obj.Submeshes.Count, "Submeshes Count");
                Assert.AreEqual((nuint)18, obj.VertexCount, "VertexCount");
                Assert.AreEqual((nuint)31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual((nuint)31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #4
0
        public void CreatePlaneTest()
        {
            var V2  = new Vector2(3, 3);
            var V2i = new Vector2i(3, 3);

            using (var obj = MDLMesh.CreatePlane(V2, V2i, MDLGeometryType.Triangles, null)) {
                Assert.IsNotNull(obj, "obj");
                Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                    MaxBounds = new Vector3(1.5f, 0, 1.5f), MinBounds = new Vector3(-1.5f, 0, -1.5f)
                }, obj.BoundingBox, "BoundingBox");
                Assert.AreEqual(1, obj.Submeshes.Count, "Submeshes Count");
                Assert.That(obj.VertexBuffers.Length, Is.GreaterThanOrEqualTo(1), "VertexBuffers Count");
                Assert.AreEqual(16, obj.VertexCount, "VertexCount");
                Assert.AreEqual(31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual(31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #5
0
        public void Setup()
        {
            if (!UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
            {
                Assert.Ignore("Requires iOS9+");
            }

            if (Runtime.Arch == Arch.SIMULATOR && IntPtr.Size == 4)
            {
                // There's a bug in the i386 version of objc_msgSend where it doesn't preserve SIMD arguments
                // when resizing the cache of method selectors for a type. So here we call all selectors we can
                // find, so that the subsequent tests don't end up producing any cache resize (radar #21630410).
                object dummy;
                using (var obj = MDLMesh.CreateBox(Vector3.Zero, Vector3i.Zero, MDLGeometryType.Triangles, true, null)) {
                    obj.AddAttribute("foo", MDLVertexFormat.Char);
//					obj.AddNormals (null, 0); // throws NSInvalidArgumentException, need to figure out valid arguments
//					obj.AddTangentBasis ("foo", "bar", "zap"); // throws "Need float or half UV components Need float or half UV components"
//					obj.AddTangentBasisWithNormals ("foo", "bar", "zap"); // throws "Need float or half UV components Reason: Need float or half UV components"
                    dummy = obj.BoundingBox;
//					obj.GenerateAmbientOcclusionTexture (1, 1, new MDLObject [] { }, "name", "name");
//					obj.GenerateAmbientOcclusionVertexColors (1, 1, new MDLObject[] {}, "name");
//					obj.GenerateAmbientOcclusionVertexColors (1.1, 1, new MDLObject[] [] { }, "name");
//					obj.GenerateLightMapTexture (Vector2i.Zero, new MDLLight[] {}, new MDLObject[] {}, "str", "str");
//					obj.GenerateLightMapVertexColors (new MDLLight[] { }, new MDLObject[] { }, "v");
                    obj.MakeVerticesUnique();
                    dummy = obj.Submeshes;
                    dummy = obj.VertexBuffers;
                    dummy = obj.VertexCount;
                    dummy = obj.VertexDescriptor;
                }

                using (var obj = MDLMesh.CreateCylindroid(1, Vector2.Zero, 3, 0, MDLGeometryType.Triangles, false, null)) {
                }
                using (var obj = MDLMesh.CreateEllipsoid(Vector3.Zero, 3, 2, MDLGeometryType.Triangles, false, false, null)) {
                }
                using (var obj = MDLMesh.CreateEllipticalCone(0, Vector2.Zero, 3, 1, MDLGeometryType.Triangles, false, null)) {
                }
                using (var obj = MDLMesh.CreateIcosahedron(0, false, null)) {
                }
                using (var obj = MDLMesh.CreatePlane(new Vector2(1, 1), new Vector2i(1, 1), MDLGeometryType.Triangles, null)) {
                }
//				using (var obj = MDLMesh.CreateSubdividedMesh (new MDLMesh (), 0, 0)) {
//				}
            }
        }
Exemple #6
0
        protected ArrayList FlattenChildren(MDLObject obj)
        {
            ArrayList ares = new ArrayList(0);

            if (obj.type == MDLType.mdl_group)
            {
                MDLMesh[] childmeshes = new MDLMesh[obj.nchildren];
                for (int i = 0; i < obj.nchildren; i++)
                {
                    ares.AddRange(FlattenChildren(obj.childrens[i]));
                }
            }
            if (obj.type == MDLType.mdl_mesh)
            {
                ares.Add(obj);
            }
            return(ares);
        }
Exemple #7
0
        public void CreateHemisphereTest()
        {
            TestRuntime.AssertXcodeVersion(8, 0);

            Vector3  V3  = new Vector3(1, 2, 3);
            Vector2i V2i = new Vector2i(4, 5);

            using (var obj = MDLMesh.CreateHemisphere(V3, V2i, MDLGeometryType.Triangles, true, true, null)) {
                Assert.IsNotNull(obj, "obj");
                Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                    MaxBounds = new Vector3(0.9510565f, 2, 2.85317f), MinBounds = new Vector3(-0.9510565f, 0.6180339f, -2.85317f)
                }, obj.BoundingBox, "BoundingBox");
                Assert.AreEqual(1, obj.Submeshes.Count, "Submeshes Count");
                Assert.AreEqual(1, obj.VertexBuffers.Length, "VertexBuffers Count");
                Assert.That(obj.VertexCount, Is.GreaterThanOrEqualTo(16), "VertexCount");
                Assert.AreEqual(31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual(31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #8
0
        public void CreateConeTest()
        {
            TestRuntime.AssertXcodeVersion(8, 0);

            Vector3  V3  = new Vector3(1, 2, 3);
            Vector2i V2i = new Vector2i(4, 5);

            using (var obj = MDLMesh.CreateCone(V3, V2i, MDLGeometryType.Triangles, true, true, null)) {
                Assert.IsNotNull(obj, "obj");
                Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                    MaxBounds = new Vector3(0.5f, -0.5f, 1.5f), MinBounds = new Vector3(-0.5f, -2.5f, -1.5f)
                }, obj.BoundingBox, "BoundingBox");
                Assert.AreEqual(1, obj.Submeshes.Count, "Submeshes Count");
                Assert.AreEqual(3, obj.VertexBuffers.Length, "VertexBuffers Count");
                Assert.AreEqual(36, obj.VertexCount, "VertexCount");
                Assert.AreEqual(31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual(31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #9
0
        public void CreateBoxTest()
        {
            Vector3  V3  = new Vector3(1, 2, 3);
            Vector3i V3i = new Vector3i(4, 5, 6);

            using (var obj = MDLMesh.CreateBox(V3, V3i, MDLGeometryType.Triangles, true, null)) {
                Assert.IsNotNull(obj, "obj");
                Asserts.AreEqual(new MDLAxisAlignedBoundingBox {
                    MaxBounds = new Vector3(0.5f, 1, 1.5f), MinBounds = new Vector3(-0.5f, -1, -1.5f)
                }, obj.BoundingBox, "BoundingBox");
                Assert.AreEqual(1, obj.Submeshes.Count, "Submeshes Count");
                Assert.AreEqual(1, obj.VertexBuffers.Length, "VertexBuffers Count");
                // iOS 9.3 is the basis of tvOS 9.2 (hopefully they'll get in sync with iOS 10+)
#if __TVOS__
                bool nine3 = UIDevice.CurrentDevice.CheckSystemVersion(9, 2);
#else
                bool nine3 = UIDevice.CurrentDevice.CheckSystemVersion(9, 3);
#endif
                Assert.AreEqual(nine3 ? 214 : 24, obj.VertexCount, "VertexCount");
                Assert.AreEqual(31, obj.VertexDescriptor.Attributes.Count, "VertexDescriptor Attributes Count");
                Assert.AreEqual(31, obj.VertexDescriptor.Layouts.Count, "VertexDescriptor Layouts Count");
            }
        }
Exemple #10
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("mesh_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("mesh_fragment");

            // Generate meshes
            MTKMeshBufferAllocator mtkBufferAllocator = new MTKMeshBufferAllocator(device);
            NSUrl     url       = NSBundle.MainBundle.GetUrlForResource("Fighter", "obj");
            MDLAsset  mdlAsset  = new MDLAsset(url, new MDLVertexDescriptor(), mtkBufferAllocator);
            MDLObject mdlObject = mdlAsset.GetObject(0);
            MDLMesh   mdlMesh   = mdlObject as MDLMesh;

            NSError error;

            objMesh = new MTKMesh(mdlMesh, device, out error);

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = MTLVertexDescriptor.FromModelIO(objMesh.VertexDescriptor);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            this.view = CreateLookAt(new Vector3(0, 1, 2), new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);

            this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = mtkView.ColorPixelFormat;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            NSImage          image            = NSImage.ImageNamed("Fighter_Diffuse.jpg");
            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            this.texture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.ClampToEdge,
                TAddressMode = MTLSamplerAddressMode.ClampToEdge,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);
        }