public void ShouldRejectDuplicateModelNames() { GeometryCacheBuilder <DefaultVertex> gcbA = new GeometryCacheBuilder <DefaultVertex>(); gcbA.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbA.AddModel("SRDMN_B", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcA = gcbA.Build(); GeometryCacheBuilder <DefaultVertex> gcbB = new GeometryCacheBuilder <DefaultVertex>(); gcbB.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbB.AddModel("SRDMN_2", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbB.AddModel("SRDMN_3", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcB = gcbB.Build(); GeometryCacheBuilder <DefaultVertex> gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_X", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Y", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcA.Dispose(); gcB.Dispose(); }
public void TestGettingModelsByName() { GeometryCacheBuilder <DefaultVertex> gcbA = new GeometryCacheBuilder <DefaultVertex>(); ModelHandle modelA = gcbA.AddModel("TGMBN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle modelB = gcbA.AddModel("TGMBN_B", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcA = gcbA.Build(); GeometryCacheBuilder <DefaultVertex> gcbB = new GeometryCacheBuilder <DefaultVertex>(); ModelHandle model1 = gcbB.AddModel("TGMBN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle model2 = gcbB.AddModel("TGMBN_2", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle model3 = gcbB.AddModel("TGMBN_3", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcB = gcbB.Build(); Assert.AreEqual(modelA, gcA.GetModelByName("TGMBN_A")); Assert.AreEqual(model3, gcB.GetModelByName("TGMBN_3")); Assert.AreEqual(model1, GeometryCache.GloballyGetModelByName("TGMBN_1")); Assert.AreEqual(model2, GeometryCache.GloballyGetModelByName("TGMBN_2")); Assert.AreEqual(modelB, GeometryCache.GloballyGetModelByName("TGMBN_B")); try { gcA.GetModelByName("TGMBN_1"); Assert.Fail(); } catch (KeyNotFoundException) { } try { gcB.GetModelByName("TGMBN_B"); Assert.Fail(); } catch (KeyNotFoundException) { } try { GeometryCache.GloballyGetModelByName("TGMBN_C"); Assert.Fail(); } catch (KeyNotFoundException) { } }
public void TestSetInputLayout() { GeometryCacheBuilder <DefaultVertex> gcb = new GeometryCacheBuilder <DefaultVertex>(); gcb.AddModel("TSIL_a", new DefaultVertex[] { new DefaultVertex(Vector3.ONE) }, new uint[] { 0U }); GeometryCache cache = gcb.Build(); ConstantBuffer <Matrix> vpMat = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); VertexShader shader = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(0U, "INSTANCE_TRANSFORM"), new ConstantBufferBinding(0U, "CameraTransform", vpMat), new VertexInputBinding(1U, "POSITION") ); GeometryInputLayout gil = cache.GetInputLayout(shader); RenderCommand testCommand = RenderCommand.SetInputLayout(gil); Assert.AreEqual(RenderCommandInstruction.SetInputLayout, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)gil.ResourceHandle, testCommand.Arg1); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetInputLayout(null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif shader.Dispose(); vpMat.Dispose(); cache.Dispose(); gil.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetInputLayout(gil); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public static Font Load(string fontFile, FragmentShader textFS, uint?lineHeightPixels, int?kerningPixels) { Assure.NotNull(fontFile); Assure.NotNull(textFS); Assure.False(textFS.IsDisposed); if (!IOUtils.IsValidFilePath(fontFile) || !File.Exists(fontFile)) { throw new FileNotFoundException("File '" + fontFile + "' not found: Could not load font."); } XDocument fontDocument = XDocument.Load(fontFile, LoadOptions.None); XElement root = fontDocument.Root; XElement commonElement = root.Element("common"); if (commonElement == null) { throw new InvalidOperationException("Could not find common element in given font file."); } string name = Path.GetFileNameWithoutExtension(fontFile).CapitalizeFirst(); uint texWidth; uint texHeight; try { texWidth = uint.Parse(commonElement.Attribute("scaleW").Value); texHeight = uint.Parse(commonElement.Attribute("scaleH").Value); if (lineHeightPixels == null) { lineHeightPixels = uint.Parse(commonElement.Attribute("lineHeight").Value) / 2U; } } catch (Exception e) { throw new InvalidOperationException("Could not read scaleW, scaleH, or lineHeight value!", e); } XElement pagesElement = root.Element("pages"); IEnumerable <XElement> pageElements = pagesElement.Elements("page"); ITexture2D[] pageArray = new ITexture2D[pageElements.Count()]; ShaderResourceView[] characterPageViews = new ShaderResourceView[pageArray.Length]; foreach (XElement pageElement in pageElements) { int id; string filename; try { id = int.Parse(pageElement.Attribute("id").Value); filename = pageElement.Attribute("file").Value; } catch (Exception e) { throw new InvalidOperationException("Could not read page ID or filename for page " + pageElement + ".", e); } string fullFilename = Path.Combine(Path.GetDirectoryName(fontFile), filename); if (!IOUtils.IsValidFilePath(fullFilename) || !File.Exists(fullFilename)) { throw new InvalidOperationException("Page file '" + fullFilename + "' does not exist!"); } if (id < 0 || id >= pageArray.Length || pageArray[id] != null) { throw new InvalidOperationException("Invalid or duplicate page ID '" + id + "'."); } pageArray[id] = TextureFactory.LoadTexture2D() .WithFilePath(fullFilename) .WithPermittedBindings(GPUBindings.ReadableShaderResource) .WithUsage(ResourceUsage.Immutable) .Create(); characterPageViews[id] = pageArray[id].CreateView(); } GeometryCacheBuilder <DefaultVertex> characterCacheBuilder = new GeometryCacheBuilder <DefaultVertex>(); Dictionary <char, FontCharacter> charMap = new Dictionary <char, FontCharacter>(); XElement charsElement = root.Element("chars"); foreach (XElement charElement in charsElement.Elements("char")) { char unicodeValue; uint x, y, width, height; int pageID, yOffset; try { unicodeValue = (char)short.Parse(charElement.Attribute("id").Value); x = uint.Parse(charElement.Attribute("x").Value); y = uint.Parse(charElement.Attribute("y").Value); width = uint.Parse(charElement.Attribute("width").Value); height = uint.Parse(charElement.Attribute("height").Value); pageID = int.Parse(charElement.Attribute("page").Value); yOffset = int.Parse(charElement.Attribute("yoffset").Value); } catch (Exception e) { throw new InvalidOperationException("Could not acquire character ID, page ID, or dimensions for char " + charElement + ".", e); } Rectangle charMapBoundary = new Rectangle(x, y, width, height); ModelHandle modelHandle = characterCacheBuilder.AddModel( "Font_" + name + "_Character_" + unicodeValue, new[] { new DefaultVertex( new Vector3(0f, 0f, 1f), Vector3.BACKWARD, new Vector2( charMapBoundary.GetCornerX(Rectangle.RectangleCorner.BottomLeft) / texWidth, charMapBoundary.GetCornerY(Rectangle.RectangleCorner.BottomLeft) / texHeight )), new DefaultVertex( new Vector3(charMapBoundary.Width, 0f, 1f), Vector3.BACKWARD, new Vector2( charMapBoundary.GetCornerX(Rectangle.RectangleCorner.BottomRight) / texWidth, charMapBoundary.GetCornerY(Rectangle.RectangleCorner.BottomRight) / texHeight )), new DefaultVertex( new Vector3(charMapBoundary.Width, -charMapBoundary.Height, 1f), Vector3.BACKWARD, new Vector2( charMapBoundary.GetCornerX(Rectangle.RectangleCorner.TopRight) / texWidth, charMapBoundary.GetCornerY(Rectangle.RectangleCorner.TopRight) / texHeight )), new DefaultVertex( new Vector3(0f, -charMapBoundary.Height, 1f), Vector3.BACKWARD, new Vector2( charMapBoundary.GetCornerX(Rectangle.RectangleCorner.TopLeft) / texWidth, charMapBoundary.GetCornerY(Rectangle.RectangleCorner.TopLeft) / texHeight )), }, new[] { 0U, 1U, 3U, 1U, 2U, 3U } ); //yOffset = 0; //if (unicodeValue == '.') yOffset = (int) (lineHeightPixels.Value * 0.9f); charMap.Add( unicodeValue, new FontCharacter( unicodeValue, charMapBoundary, modelHandle, textFS, characterPageViews[pageID], yOffset ) ); } if (kerningPixels == null) { kerningPixels = (int)(charMap.Values.Max(value => value.Boundary.Width) * 0.15f); } uint maxCharHeight = (uint)charMap.Values.Max(fc => fc.Boundary.Height); return(new Font( name, lineHeightPixels.Value, kerningPixels.Value, characterCacheBuilder.Build(), pageArray, characterPageViews, charMap, (ConstantBufferBinding)textFS.GetBindingByIdentifier(TEXT_COLOR_SHADER_CB_NAME), maxCharHeight )); }
public unsafe void TestCreateAndDestroyInstance() { // Define variables and constants const int NUM_INSTANCES = 1000; var gcb = new GeometryCacheBuilder <TestVertex>(); gcb.AddModel("TCADI_a", new[] { new TestVertex(Vector3.ONE), new TestVertex(Vector3.LEFT), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); gcb.AddModel("TCADI_b", new[] { new TestVertex(Vector3.RIGHT), new TestVertex(Vector3.UP), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); gcb.AddModel("TCADI_c", new[] { new TestVertex(Vector3.ZERO), new TestVertex(Vector3.DOWN), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); GeometryCache testCache = gcb.Build(); SceneLayer testLayerA = Scene.CreateLayer("Test Layer A"); SceneLayer testLayerB = Scene.CreateLayer("Test Layer B"); ConstantBuffer <Vector4> fsColorBuffer = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); FragmentShader fs = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", fsColorBuffer)); Material testMatA = new Material("Brick", fs); Material testMatB = new Material("Wood", fs); // Set up context // Execute ModelInstanceHandle[] instanceArr = new ModelInstanceHandle[NUM_INSTANCES]; for (int i = 0; i < NUM_INSTANCES; ++i) { Transform transform = new Transform( Vector3.ONE * i, Quaternion.FromAxialRotation(Vector3.UP, i), Vector3.ONE * -i ); if (i % 5 == 0) { instanceArr[i] = testLayerA.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform); } else { instanceArr[i] = testLayerB.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform); } } // Assert outcome RenderingModule.RenderStateBarrier.FreezeMutations(); // Cheeky, but we have to on debug mode (and it's re-entrant for now, so no problem) var instanceData = testCache.GetModelInstanceData(); for (int i = 0; i < NUM_INSTANCES; ++i) { Material instanceMaterial = Material.GetMaterialByIndex(instanceArr[i].MaterialIndex); ModelInstanceManager.MIDArray materialDataArray = instanceData.First(kvp => kvp.Key == instanceMaterial).Value; Assert.AreEqual((i % 2 == 0 ? testMatA : testMatB), instanceMaterial); Assert.AreEqual((i % 5 == 0 ? testLayerA : testLayerB), Scene.GetLayerByIndex(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].SceneLayerIndex)); Assert.IsTrue(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse); Assert.AreEqual((uint)(i % 3), materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].ModelIndex); Assert.AreEqual( new Transform( Vector3.ONE * i, Quaternion.FromAxialRotation(Vector3.UP, i), Vector3.ONE * -i ), instanceArr[i].Transform ); Assert.AreEqual(instanceArr[i].Transform, materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].Transform); instanceArr[i].Dispose(); Assert.IsFalse(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse); } RenderingModule.RenderStateBarrier.UnfreezeMutations(); testCache.Dispose(); testMatA.Dispose(); testMatB.Dispose(); testLayerA.Dispose(); testLayerB.Dispose(); fs.Dispose(); fsColorBuffer.Dispose(); }
public void ShouldCookParametersCorrectly() { // Define variables and constants GeometryCacheBuilder <TestVertex> testVertexCacheBuilder = new GeometryCacheBuilder <TestVertex>(); int cacheID = (int)typeof(GeometryCacheBuilder <TestVertex>).GetField("cacheID", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(testVertexCacheBuilder); TestVertex[] model1Verts = { new TestVertex(Vector3.ONE * 0f, Vector2.ONE * 0f), new TestVertex(Vector3.ONE * 1f, Vector2.ONE * 1f), new TestVertex(Vector3.ONE * 2f, Vector2.ONE * 2f), }; TestVertex[] model2Verts = { new TestVertex(Vector3.ONE * 3f, Vector2.ONE * 3f), new TestVertex(Vector3.ONE * 4f, Vector2.ONE * 4f), new TestVertex(Vector3.ONE * 5f, Vector2.ONE * 5f), }; uint[] model1Indices = { 0U, 1U, 2U, 1U, 2U, 0U, 2U, 0U, 1U }; uint[] model2Indices = { 3U, 4U, 5U, 4U, 5U, 3U, 5U, 3U, 4U, 3U, 5U, 4U }; uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount; // Set up context Assert.AreEqual(new ModelHandle(cacheID, 0U), testVertexCacheBuilder.AddModel("SCPC_a", model1Verts, model1Indices)); Assert.AreEqual(new ModelHandle(cacheID, 1U), testVertexCacheBuilder.AddModel("SCPC_b", model2Verts, model2Indices)); // Execute GeometryCache result = testVertexCacheBuilder.Build(); // Assert outcome Assert.AreEqual(cacheID, result.ID); Assert.AreEqual(result, GeometryCache.GetCacheByID(cacheID)); Assert.AreEqual((uint)(model1Indices.Length + model2Indices.Length), result.IndexBuffer.Length); Assert.AreEqual((uint)(model1Verts.Length + model2Verts.Length), result.VertexBuffers[0].Length); Assert.AreEqual(2, result.VertexBuffers.Count); Assert.AreEqual(ResourceFormat.R32G32B32Float, result.VertexFormats[0]); Assert.AreEqual(ResourceFormat.R32G32Float, result.VertexFormats[1]); Assert.AreEqual(2U, result.NumModels); Assert.AreEqual(6U, result.NumVertices); Assert.AreEqual(typeof(VertexBuffer <Vector3>), result.VertexBuffers[0].GetType()); Assert.AreEqual(typeof(VertexBuffer <Vector2>), result.VertexBuffers[1].GetType()); Assert.AreEqual("POSITION", result.VertexSemantics[0]); Assert.AreEqual("TEXCOORD", result.VertexSemantics[1]); result.GetModelBufferValues(0U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.AreEqual(0U, outVBStartIndex); Assert.AreEqual(0U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(9U, outIBCount); result.GetModelBufferValues(1U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.AreEqual(3U, outVBStartIndex); Assert.AreEqual(9U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(12U, outIBCount); #if !DEVELOPMENT && !RELEASE try { result.GetModelBufferValues(2U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.Fail(); } catch (AssuranceFailedException) { } #endif result.Dispose(); }