protected HexMapMesh(GraphicsDevice gd, List <Hexagon> hexes, IGeometryBuilder builder, Texture2D texture) { Interlocked.Increment(ref meshCounter); Texture = texture; Hexes = hexes; PatchID = meshCounter; Vertices = new List <VertexPositionNormalTexture>(); Indices = new List <uint>(); TriangleCount = hexes.Count * 6; HexSize = hexes[0].Geometry.HexWidth; foreach (var hexagon in hexes) { hexagon.PatchID = PatchID; } builder.BuildGeometry(hexes, Vertices, Indices); BoundingBox = hexes[0].Geometry.BoundingBox; foreach (var hexagon in hexes.Skip(1)) { BoundingBox = BoundingBox.CreateMerged(BoundingBox, hexagon.Geometry.BoundingBox); } VertexBuffer = new VertexBuffer(gd, typeof(VertexPositionNormalTexture), Vertices.Count, BufferUsage.WriteOnly); var vpcs = Vertices.ToArray(); builder.GenerateNormals(vpcs, Indices); VertexBuffer.SetData(vpcs); IndexBuffer = new IndexBuffer(gd, IndexElementSize.ThirtyTwoBits, Indices.Count, BufferUsage.WriteOnly); IndexBuffer.SetData(Indices.ToArray()); Grid = new HexGrid(gd, Hexes, Color.Gray); }
public static void CreateSolid(this IGeometryBuilder builder, int tessellation) { Vector3 offset = new Vector3(0, -0.25f, 0); builder.AddVertex(Vector3.UnitY + offset, Vector3.UnitY); builder.AddVertex(Vector3.Zero + offset, -Vector3.UnitY); for (int i = 0; i < tessellation; ++i) { float angle = i * Algorithms.Helpers.TwoPi / tessellation; float dx = MathF.Cos(angle); float dz = MathF.Sin(angle); Vector3 normal = new Vector3(dx, 0, dz); builder.AddVertex(normal + offset, normal); builder.AddIndex(0); builder.AddIndex(2 + i); builder.AddIndex(2 + (i + 1) % tessellation); builder.AddIndex(1); builder.AddIndex(2 + (i + 1) % tessellation); builder.AddIndex(2 + i); } }
private void OnGUI() { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label("Primitive"); var index = Mathf.Max(EditorGUILayout.Popup(_selectedBuilderIndex, _builderNames.ToArray()), 0); GUILayout.EndHorizontal(); if (index >= 0 && _renderers.Count > index) { if (index != _selectedBuilderIndex || null == _renderer) { _settings = (GeometryBuilderSettings)GeometryProvider.Factories[index].Invoke(null, null); _renderer = _renderers[index]; _builder = GeometryProvider.Builders[index]; _settings.Name = Name(_builder); _settings.Description = Description(_builder); } _renderer.Draw(_settings); _selectedBuilderIndex = index; } GUILayout.EndVertical(); }
private static IGeometryBuilderRenderer Renderer(IGeometryBuilder builder) { var builderType = builder.GetType(); var rendererTypes = typeof(IGeometryBuilderRenderer).Implementors(); foreach (var rendererType in rendererTypes) { var customRenderer = rendererType.Attribute <CustomRenderer>(); if (null == customRenderer) { continue; } if (customRenderer.Type == builderType) { try { var customRendererInstance = (IGeometryBuilderRenderer)Activator.CreateInstance(rendererType); return(customRendererInstance); } catch { Debug.LogError(string.Format( "Could not instantiate custom IGeometryBuilderRenderer {0}. Does it have a public default constructor?", rendererType)); break; } } } return(new StandardGeometryBuilderRenderer()); }
private void _ReadGeometry(JsonReader reader, IGeometryBuilder builder, GeometryType type) { switch (type) { case GeometryType.GeometryCollection: case GeometryType.MultiLineString: //case GeometryType.MultiPoint: case GeometryType.MultiPolygon: case GeometryType.Polygon: if (reader.TokenType != JsonToken.StartArray) { throw new JsonReaderException(SR.InvalidGeoJsonLineInfoException); } if (!reader.Read()) { _ThrowGeoJsonException(reader, null); } break; } builder.BeginGeometry(type); switch (type) { case GeometryType.MultiPolygon: do { _ReadGeometry(reader, builder, GeometryType.Polygon); } while ((reader.TokenType != JsonToken.EndArray) && (reader.TokenType != JsonToken.EndObject)); break; default: do { _ReadFigure(reader, builder, type); } while ((reader.TokenType != JsonToken.EndArray) && (reader.TokenType != JsonToken.EndObject)); break; } switch (type) { case GeometryType.GeometryCollection: case GeometryType.MultiLineString: //case GeometryType.MultiPoint: case GeometryType.MultiPolygon: case GeometryType.Polygon: if (reader.TokenType != JsonToken.EndArray) { _ThrowGeoJsonException(reader, JsonToken.EndArray); } if (!reader.Read()) { _ThrowGeoJsonException(reader, null); } break; } builder.EndGeometry(); }
private static string Description(IGeometryBuilder builder) { var builderType = builder.GetType(); var customName = builderType.Attribute <DescriptionAttribute>(); if (null != customName) { return(customName.Description); } return("[No description]"); }
private static string Name(IGeometryBuilder builder) { var builderType = builder.GetType(); var customName = builderType.Attribute <DisplayNameAttribute>(); if (null != customName) { return(customName.DisplayName); } return(builderType.Name); }
private void _ReadFigure(JsonReader reader, IGeometryBuilder builder, GeometryType type) { if (type != GeometryType.Point) { if (reader.TokenType != JsonToken.StartArray) { _ThrowGeoJsonException(reader, JsonToken.StartArray); } if (!reader.Read() || (reader.TokenType != JsonToken.StartArray)) { _ThrowGeoJsonException(reader, JsonToken.StartArray); } } bool first = true; do { if (!reader.Read()) { _ThrowGeoJsonException(reader, null); } var p = _ReadPoint(reader); if (first) { builder.BeginFigure(p.X, p.Y, p.Z); first = false; } else { builder.AddLine(p.X, p.Y, p.Z); } } while (reader.TokenType == JsonToken.StartArray); if (type != GeometryType.Point) { if (reader.TokenType != JsonToken.EndArray) { _ThrowGeoJsonException(reader, JsonToken.EndArray); } if (!reader.Read()) { _ThrowGeoJsonException(reader, null); } } builder.EndFigure(); }
/// <summary> /// Retrieves a factory. /// </summary> /// <param name="builder"></param> /// <param name="factories"></param> /// <returns></returns> private static MethodInfo Factory( IGeometryBuilder builder, MethodInfo[] factories) { foreach (var method in factories) { var attribute = method.Attribute <CustomFactory>(); if (null != attribute && attribute.Type == builder.GetType()) { return(method); } } return(typeof(GeometryProvider).GetMethod( "DefaultFactory", BindingFlags.Static | BindingFlags.NonPublic)); }
public static void CreateSolid(this IGeometryBuilder builder, int tessellation) { // First we loop around the main ring of the torus. for (int i = 0; i < tessellation; ++i) { float outerAngle = i * Algorithms.Helpers.TwoPi / tessellation; // Create a transform matrix that will align geometry to // slice perpendicularly though the current ring position. var transform = Matrix4x4.CreateTranslation(1, 0, 0) * Matrix4x4.CreateRotationY(outerAngle); // Now we loop along the other axis, around the side of the tube. for (int j = 0; j < tessellation; j++) { float innerAngle = j * Algorithms.Helpers.TwoPi / tessellation; float dx = MathF.Cos(innerAngle); float dy = MathF.Sin(innerAngle); // Create a vertex. Vector3 normal = new Vector3(dx, dy, 0); Vector3 position = normal / 2.0f; position = Vector3.Transform(position, transform); normal = Vector3.TransformNormal(normal, transform); builder.AddVertex(position, normal); // And create indices for two triangles. int nextI = (i + 1) % tessellation; int nextJ = (j + 1) % tessellation; builder.AddIndex(i * tessellation + j); builder.AddIndex(i * tessellation + nextJ); builder.AddIndex(nextI * tessellation + j); builder.AddIndex(i * tessellation + nextJ); builder.AddIndex(nextI * tessellation + nextJ); builder.AddIndex(nextI * tessellation + j); } } }
/// <summary>Parses the geometry defined by the specified WKT representation, in the specified coordinate system.</summary> /// <param name="text">The WKT representation of the geometry.</param> /// <param name="system">The coordinate system of the WKT representation.</param> public void Parse(string text, ICoordinateSystem system) { Debug.Assert(system != null); if (system == null) { throw new ArgumentNullException("system"); } IGeometryBuilder builder = CreateBuilder(system); builder.Parse(text, system); IGeometry g = (IGeometry)builder.ConstructedGeometry; if ((TargetSystem != null) && !system.IsEquivalentTo(TargetSystem)) { g.Populate(this); } else { _Geometry = g; } }
public static void CreateSolid(this IGeometryBuilder builder, Vector3 size) { for (int i = 0; i < normals.Length; i++) { var normal = normals[i]; Vector3 side1 = new Vector3(normal.Y, normal.Z, normal.X); Vector3 side2 = Vector3.Cross(normal, side1); builder.AddIndex(builder.CurrentVertex + 0); builder.AddIndex(builder.CurrentVertex + 1); builder.AddIndex(builder.CurrentVertex + 2); builder.AddIndex(builder.CurrentVertex + 0); builder.AddIndex(builder.CurrentVertex + 2); builder.AddIndex(builder.CurrentVertex + 3); builder.AddVertex(((normal - side1 - side2) / 2.0f) * size, normal, Vector2.Zero); builder.AddVertex(((normal - side1 + side2) / 2.0f) * size, normal, Vector2.UnitX); builder.AddVertex(((normal + side1 + side2) / 2.0f) * size, normal, Vector2.One); builder.AddVertex(((normal + side1 - side2) / 2.0f) * size, normal, Vector2.UnitY); } }
public static void CreateSolid(this IGeometryBuilder builder, Vector3 start, Vector3 end, float radius, int tessellation) { builder.AddVertex(start * 0.5f, start); builder.AddVertex(-end * 0.5f, -end); float diameter = radius / 2.0f; for (int i = 0; i < tessellation; ++i) { float angle = i * Algorithms.Helpers.TwoPi / tessellation; float dx = MathF.Cos(angle); float dz = MathF.Sin(angle); Vector3 normal = new Vector3(dx, 0.0f, dz); builder.AddVertex(normal + (diameter * start), normal); builder.AddVertex(normal - (diameter * start), normal); builder.AddIndex(0); builder.AddIndex(2 + (i * 2)); builder.AddIndex(2 + (((i * 2) + 2) % (tessellation * 2))); builder.AddIndex(2 + (i * 2)); builder.AddIndex(2 + (i * 2) + 1); builder.AddIndex(2 + (((i * 2) + 2) % (tessellation * 2))); builder.AddIndex(1); builder.AddIndex(2 + (((i * 2) + 3) % (tessellation * 2))); builder.AddIndex(2 + (i * 2) + 1); builder.AddIndex(2 + (i * 2) + 1); builder.AddIndex(2 + (((i * 2) + 3) % (tessellation * 2))); builder.AddIndex(2 + (((i * 2) + 2) % (tessellation * 2))); } }
public static void CreateSolid(this IGeometryBuilder builder, float radius, int tessellation) => CreateSolid(builder, Vector3.UnitY, -Vector3.UnitY, radius, tessellation);
/// <summary> /// Builds geometry. /// </summary> /// <param name="mesh"></param> /// <param name="builder"></param> /// <param name="settings"></param> public static void Build( Mesh mesh, IGeometryBuilder builder, GeometryBuilderSettings settings) { if (null == mesh || null == builder || null == settings) { return; } // begin flow builder.Start(mesh, settings); // create buffers int[] triangles = null; Vector3[] vertices = null; Vector2[] uvs = null; Vector2[] uv1s = null; Vector2[] uv2s = null; Vector3[] normals = null; Color[] colors = null; // must always have a layout builder.Layout(out vertices, out triangles); settings.Vertex.Transform(ref vertices, ref triangles); // fill other buffers if (settings.UV.Enabled) { builder.UV(out uvs, settings.UV); settings.UV.Transform(ref uvs); } if (settings.UV1.Enabled) { builder.UV(out uv1s, settings.UV1); settings.UV1.Transform(ref uv1s); } if (settings.UV2.Enabled) { builder.UV(out uv2s, settings.UV2); settings.UV2.Transform(ref uv2s); } if (settings.Color.Enabled) { builder.Colors(out colors); settings.Color.Transform(ref colors); } if (settings.Normals.Enabled) { builder.Normals(out normals); settings.Normals.Transform(ref normals); } // set buffers, layout first mesh.SetLayout(ref vertices, ref triangles); mesh.uv = uvs; mesh.uv2 = uv1s; mesh.uv2 = uv2s; mesh.colors = colors; mesh.normals = normals; }
public static void CreateSolid(this IGeometryBuilder builder, float radius) => CreateSolid(builder, Vector3.UnitY, -Vector3.UnitY, radius, 32);
private void _ReadFigure(JsonReader reader, IGeometryBuilder builder, GeometryType type) { if (type!=GeometryType.Point) { if (reader.TokenType!=JsonToken.StartArray) _ThrowGeoJsonException(reader, JsonToken.StartArray); if (!reader.Read() || (reader.TokenType!=JsonToken.StartArray)) _ThrowGeoJsonException(reader, JsonToken.StartArray); } bool first=true; do { if (!reader.Read()) _ThrowGeoJsonException(reader, null); var p=_ReadPoint(reader); if (first) { builder.BeginFigure(p.X, p.Y, p.Z); first=false; } else builder.AddLine(p.X, p.Y, p.Z); } while (reader.TokenType==JsonToken.StartArray); if (type!=GeometryType.Point) { if (reader.TokenType!=JsonToken.EndArray) _ThrowGeoJsonException(reader, JsonToken.EndArray); if (!reader.Read()) _ThrowGeoJsonException(reader, null); } builder.EndFigure(); }
private void _ReadGeometry(JsonReader reader, IGeometryBuilder builder, GeometryType type) { switch (type) { case GeometryType.GeometryCollection: case GeometryType.MultiLineString: //case GeometryType.MultiPoint: case GeometryType.MultiPolygon: case GeometryType.Polygon: if (reader.TokenType!=JsonToken.StartArray) throw new JsonReaderException(SR.InvalidGeoJsonLineInfoException); if (!reader.Read()) _ThrowGeoJsonException(reader, null); break; } builder.BeginGeometry(type); switch (type) { case GeometryType.MultiPolygon: do { _ReadGeometry(reader, builder, GeometryType.Polygon); } while ((reader.TokenType!=JsonToken.EndArray) && (reader.TokenType!=JsonToken.EndObject)); break; default: do { _ReadFigure(reader, builder, type); } while ((reader.TokenType!=JsonToken.EndArray) && (reader.TokenType!=JsonToken.EndObject)); break; } switch (type) { case GeometryType.GeometryCollection: case GeometryType.MultiLineString: //case GeometryType.MultiPoint: case GeometryType.MultiPolygon: case GeometryType.Polygon: if (reader.TokenType!=JsonToken.EndArray) _ThrowGeoJsonException(reader, JsonToken.EndArray); if (!reader.Read()) _ThrowGeoJsonException(reader, null); break; } builder.EndGeometry(); }
public static void CreateSolid(this IGeometryBuilder builder) => CreateSolid(builder, 1.0f, 12);
public static void CreateSolid(this IGeometryBuilder builder, float radius, int tessellation) { int verticalSegments = tessellation; int horizontalSegments = tessellation * 2; // Start with a single vertex at the bottom of the sphere. builder.AddVertex(Vector3.UnitY, -Vector3.UnitY); // Create rings of vertices at progressively higher latitudes. for (int i = 0; i < verticalSegments - 1; ++i) { float latitude = ((i + 1.0f) * Algorithms.Helpers.Pi / verticalSegments) - Algorithms.Helpers.PiOver2; float dy = MathF.Sin(latitude); float dxz = MathF.Cos(latitude); // Create a single ring of vertices at this latitude. for (int j = 0; j < horizontalSegments; j++) { float longitude = j * Algorithms.Helpers.TwoPi / horizontalSegments; float dx = MathF.Cos(longitude) * dxz; float dz = MathF.Sin(longitude) * dxz; Vector3 normal = new Vector3(dx, dy, dz) * radius; builder.AddVertex(normal, normal); } } // Finish with a single vertex at the top of the sphere. builder.AddVertex(Vector3.UnitY, Vector3.UnitY); // Create a fan connecting the bottom vertex to the bottom latitude ring. for (int i = 0; i < horizontalSegments; ++i) { builder.AddIndex(0); builder.AddIndex(1 + ((i + 1) % horizontalSegments)); builder.AddIndex(1 + i); } // Fill the sphere body with triangles joining each pair of latitude rings. for (int i = 0; i < verticalSegments - 2; ++i) { for (int j = 0; j < horizontalSegments; j++) { int nextI = i + 1; int nextJ = (j + 1) % horizontalSegments; builder.AddIndex(1 + (i * horizontalSegments) + j); builder.AddIndex(1 + (i * horizontalSegments) + nextJ); builder.AddIndex(1 + (nextI * horizontalSegments) + j); builder.AddIndex(1 + (i * horizontalSegments) + nextJ); builder.AddIndex(1 + (nextI * horizontalSegments) + nextJ); builder.AddIndex(1 + (nextI * horizontalSegments) + j); } } // Create a fan connecting the top vertex to the top latitude ring. for (int i = 0; i < horizontalSegments; ++i) { builder.AddIndex(builder.CurrentVertex - 1); builder.AddIndex(builder.CurrentVertex - 2 - ((i + 1) % horizontalSegments)); builder.AddIndex(builder.CurrentVertex - 2 - i); } }
public static void CreateSolid(this IGeometryBuilder builder, float radius) => CreateSolid(builder, radius, 12);
public void BuildGeometry(IGeometryBuilder geometryBuilder) { // An icosahedron can be created from the vertices of three intersecting golden rectangles. // https://en.wikipedia.org/wiki/Golden_rectangle List <Vector3> v = new List <Vector3>(); const float goldenRatio = 1.6180339887498948482045868343656f; // plane with z = 0 v.Add(new Vector3(-1, -goldenRatio, 0)); v.Add(new Vector3(1, -goldenRatio, 0)); v.Add(new Vector3(1, goldenRatio, 0)); v.Add(new Vector3(-1, goldenRatio, 0)); // plane with y = 0 v.Add(new Vector3(-goldenRatio, 0, -1)); v.Add(new Vector3(goldenRatio, 0, -1)); v.Add(new Vector3(goldenRatio, 0, 1)); v.Add(new Vector3(-goldenRatio, 0, 1)); // plane with x = 0 v.Add(new Vector3(0, -1, -goldenRatio)); v.Add(new Vector3(0, 1, -goldenRatio)); v.Add(new Vector3(0, 1, goldenRatio)); v.Add(new Vector3(0, -1, goldenRatio)); // Normalize them so the points sit on the unit sphere for (int i = 0; i < v.Count; i++) { v[i].Normalize(); } int[] vertexIndices = new[] { 1, 6, 10, 2, 13, 3, 2, 10, 11, 7, 3, 10, 19, 11, 10, 6, 9, 7, 10, 11, 3, 1, 11, 6, 17, 1, 6, 5, 7, 5, 6, 2, 15, 9, 5, 2, 5, 9, 2, 3, 16, 11, 1, 0, 8, 1, 8, 0, 10, 5, 8, 1, 2, 9, 4, 8, 18, 3, 4, 9, 4, 3, 7, 4, 6, 11, 0, 7, 12, 5, 9, 8, 20, 4, 0, 8, 14, 7, 0, 4, 000000000 }; for (int i = 0; i < 20; i++) { int startIndex = 4 * i; geometryBuilder.AddTriangle(vertexIndices[startIndex] - 1, v[vertexIndices[startIndex + 1]], v[vertexIndices[startIndex + 2]], v[vertexIndices[startIndex + 3]]); } }