|
|
@@ -3,32 +3,63 @@ using System.Collections.Generic;
|
|
|
using System.Numerics;
|
|
|
using System.Text;
|
|
|
|
|
|
+using SharpGLTF.Geometry;
|
|
|
+using SharpGLTF.Geometry.VertexTypes;
|
|
|
+
|
|
|
namespace SharpGLTF.Schema2.Authoring
|
|
|
{
|
|
|
- using Geometry;
|
|
|
+ using VERTEX = VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexEmpty>;
|
|
|
|
|
|
- using VEMPTY = Geometry.VertexTypes.VertexEmpty;
|
|
|
- using VPOS = Geometry.VertexTypes.VertexPosition;
|
|
|
- using VPOSNRM = Geometry.VertexTypes.VertexPositionNormal;
|
|
|
- using VTEX1 = Geometry.VertexTypes.VertexTexture1;
|
|
|
+ interface IParametricShape<TMaterial>
|
|
|
+ {
|
|
|
+ void AddTo(IMeshBuilder<TMaterial> meshBuilder, Matrix4x4 xform);
|
|
|
+ }
|
|
|
|
|
|
- static class SolidMeshUtils
|
|
|
+ class Cube<TMaterial> : IParametricShape<TMaterial>
|
|
|
{
|
|
|
- public static void AddCube<TMaterial>(this MeshBuilder<TMaterial, VPOSNRM, VEMPTY, VEMPTY> meshBuilder, TMaterial material, Matrix4x4 xform)
|
|
|
+ #region lifecycle
|
|
|
+
|
|
|
+ public Cube(TMaterial material)
|
|
|
{
|
|
|
- var p = meshBuilder.UsePrimitive(material);
|
|
|
+ _Front = _Back = _Left = _Right = _Top = _Bottom = material;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
|
|
|
- p._AddCubeFace(Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ, xform);
|
|
|
- p._AddCubeFace(-Vector3.UnitX, Vector3.UnitZ, Vector3.UnitY, xform);
|
|
|
+ #region data
|
|
|
|
|
|
- p._AddCubeFace(Vector3.UnitY, Vector3.UnitZ, Vector3.UnitX, xform);
|
|
|
- p._AddCubeFace(-Vector3.UnitY, Vector3.UnitX, Vector3.UnitZ, xform);
|
|
|
+ private Vector3 _Size = Vector3.One;
|
|
|
|
|
|
- p._AddCubeFace(Vector3.UnitZ, Vector3.UnitX, Vector3.UnitY, xform);
|
|
|
- p._AddCubeFace(-Vector3.UnitZ, Vector3.UnitY, Vector3.UnitX, xform);
|
|
|
+ private TMaterial _Front;
|
|
|
+ private TMaterial _Back;
|
|
|
+
|
|
|
+ private TMaterial _Left;
|
|
|
+ private TMaterial _Right;
|
|
|
+
|
|
|
+ private TMaterial _Top;
|
|
|
+ private TMaterial _Bottom;
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region API
|
|
|
+
|
|
|
+ public void AddTo(IMeshBuilder<TMaterial> meshBuilder, Matrix4x4 xform)
|
|
|
+ {
|
|
|
+ var x = Vector3.UnitX * _Size.X * 0.5f;
|
|
|
+ var y = Vector3.UnitY * _Size.Y * 0.5f;
|
|
|
+ var z = Vector3.UnitZ * _Size.Z * 0.5f;
|
|
|
+
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Right), x, y, z, xform);
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Left), -x, z, y, xform);
|
|
|
+
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Top), y, z, x, xform);
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Bottom), -y, x, z, xform);
|
|
|
+
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Front), z, x, y, xform);
|
|
|
+ _AddCubeFace(meshBuilder.UsePrimitive(_Back), -z, y, x, xform);
|
|
|
}
|
|
|
|
|
|
- private static void _AddCubeFace<TMaterial>(this PrimitiveBuilder<TMaterial, VPOSNRM, VEMPTY, VEMPTY> primitiveBuilder, Vector3 origin, Vector3 axisX, Vector3 axisY, Matrix4x4 xform)
|
|
|
+ private static void _AddCubeFace(IPrimitiveBuilder primitiveBuilder, Vector3 origin, Vector3 axisX, Vector3 axisY, Matrix4x4 xform)
|
|
|
{
|
|
|
var p1 = Vector3.Transform(origin - axisX - axisY, xform);
|
|
|
var p2 = Vector3.Transform(origin + axisX - axisY, xform);
|
|
|
@@ -38,72 +69,109 @@ namespace SharpGLTF.Schema2.Authoring
|
|
|
|
|
|
primitiveBuilder.AddConvexPolygon
|
|
|
(
|
|
|
- new VPOSNRM(p1, n),
|
|
|
- new VPOSNRM(p2, n),
|
|
|
- new VPOSNRM(p3, n),
|
|
|
- new VPOSNRM(p4, n)
|
|
|
+ new VERTEX( (p1, n), (Vector4.One, Vector2.Zero) ),
|
|
|
+ new VERTEX( (p2, n), (Vector4.One, Vector2.UnitX) ),
|
|
|
+ new VERTEX( (p3, n), (Vector4.One, Vector2.One) ),
|
|
|
+ new VERTEX( (p4, n), (Vector4.One, Vector2.UnitY) )
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- public static void AddSphere<TMaterial>(this MeshBuilder<TMaterial, VPOSNRM, VEMPTY, VEMPTY> meshBuilder, TMaterial material, Single radius, Matrix4x4 xform)
|
|
|
+ public MeshBuilder<TMaterial, VertexPositionNormal, VertexColor1Texture1, VertexEmpty> ToMesh(Matrix4x4 xform)
|
|
|
+ {
|
|
|
+ var mesh = new MeshBuilder<TMaterial, VertexPositionNormal, VertexColor1Texture1, VertexEmpty>();
|
|
|
+
|
|
|
+ AddTo(mesh, xform);
|
|
|
+
|
|
|
+ return mesh;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+
|
|
|
+ class IcoSphere<TMaterial> : IParametricShape<TMaterial>
|
|
|
+ {
|
|
|
+ #region lifecycle
|
|
|
+
|
|
|
+ public IcoSphere(TMaterial material, float radius = 0.5f)
|
|
|
+ {
|
|
|
+ _Material = material;
|
|
|
+ _Radius = radius;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region data
|
|
|
+
|
|
|
+ private float _Radius = 0.5f;
|
|
|
+ private TMaterial _Material;
|
|
|
+ private int _Subdivision = 3;
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region API
|
|
|
+
|
|
|
+ public void AddTo(IMeshBuilder<TMaterial> meshBuilder, Matrix4x4 xform)
|
|
|
{
|
|
|
// http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
|
|
|
|
|
|
var t = 1 + (float)(Math.Sqrt(5.0) / 2);
|
|
|
|
|
|
- var v0 = new Vector3(-1, t, 0) * radius;
|
|
|
- var v1 = new Vector3(1, t, 0) * radius;
|
|
|
- var v2 = new Vector3(-1, -t, 0) * radius;
|
|
|
- var v3 = new Vector3(1, -t, 0) * radius;
|
|
|
+ var v0 = new Vector3(-1, t, 0) * _Radius;
|
|
|
+ var v1 = new Vector3(1, t, 0) * _Radius;
|
|
|
+ var v2 = new Vector3(-1, -t, 0) * _Radius;
|
|
|
+ var v3 = new Vector3(1, -t, 0) * _Radius;
|
|
|
|
|
|
- var v4 = new Vector3(0, -1, t) * radius;
|
|
|
- var v5 = new Vector3(0, 1, t) * radius;
|
|
|
- var v6 = new Vector3(0, -1, -t) * radius;
|
|
|
- var v7 = new Vector3(0, 1, -t) * radius;
|
|
|
+ var v4 = new Vector3(0, -1, t) * _Radius;
|
|
|
+ var v5 = new Vector3(0, 1, t) * _Radius;
|
|
|
+ var v6 = new Vector3(0, -1, -t) * _Radius;
|
|
|
+ var v7 = new Vector3(0, 1, -t) * _Radius;
|
|
|
|
|
|
- var v8 = new Vector3(t, 0, -1) * radius;
|
|
|
- var v9 = new Vector3(t, 0, 1) * radius;
|
|
|
- var v10 = new Vector3(-t, 0, -1) * radius;
|
|
|
- var v11 = new Vector3(-t, 0, 1) * radius;
|
|
|
+ var v8 = new Vector3(t, 0, -1) * _Radius;
|
|
|
+ var v9 = new Vector3(t, 0, 1) * _Radius;
|
|
|
+ var v10 = new Vector3(-t, 0, -1) * _Radius;
|
|
|
+ var v11 = new Vector3(-t, 0, 1) * _Radius;
|
|
|
+
|
|
|
+ var prim = meshBuilder.UsePrimitive(_Material);
|
|
|
|
|
|
// 5 faces around point 0
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v0, v11, v5, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v0, v5, v1, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v0, v1, v7, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v0, v7, v10, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v0, v10, v11, 3);
|
|
|
+ _AddSphereFace(prim, xform, v0, v11, v5, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v0, v5, v1, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v0, v1, v7, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v0, v7, v10, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v0, v10, v11, _Subdivision);
|
|
|
|
|
|
// 5 adjacent faces
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v1, v5, v9, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v5, v11, v4, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v11, v10, v2, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v10, v7, v6, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v7, v1, v8, 3);
|
|
|
+ _AddSphereFace(prim, xform, v1, v5, v9, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v5, v11, v4, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v11, v10, v2, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v10, v7, v6, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v7, v1, v8, _Subdivision);
|
|
|
|
|
|
// 5 faces around point 3
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v3, v9, v4, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v3, v4, v2, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v3, v2, v6, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v3, v6, v8, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v3, v8, v9, 3);
|
|
|
+ _AddSphereFace(prim, xform, v3, v9, v4, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v3, v4, v2, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v3, v2, v6, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v3, v6, v8, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v3, v8, v9, _Subdivision);
|
|
|
|
|
|
// 5 adjacent faces
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v4, v9, v5, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v2, v4, v11, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v6, v2, v10, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v8, v6, v7, 3);
|
|
|
- meshBuilder._AddSphereTriangle(material, xform, v9, v8, v1, 3);
|
|
|
+ _AddSphereFace(prim, xform, v4, v9, v5, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v2, v4, v11, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v6, v2, v10, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v8, v6, v7, _Subdivision);
|
|
|
+ _AddSphereFace(prim, xform, v9, v8, v1, _Subdivision);
|
|
|
}
|
|
|
|
|
|
- private static void _AddSphereTriangle<TMaterial>(this MeshBuilder<TMaterial, VPOSNRM, VEMPTY, VEMPTY> meshBuilder, TMaterial material, Matrix4x4 xform, Vector3 a, Vector3 b, Vector3 c, int iterations = 0)
|
|
|
+ private static void _AddSphereFace(IPrimitiveBuilder primitiveBuilder, Matrix4x4 xform, Vector3 a, Vector3 b, Vector3 c, int iterations = 0)
|
|
|
{
|
|
|
- if (iterations <=0)
|
|
|
+ if (iterations <= 0)
|
|
|
{
|
|
|
- var aa = new VPOSNRM(Vector3.Transform(a, xform), Vector3.Normalize(Vector3.TransformNormal(a, xform)));
|
|
|
- var bb = new VPOSNRM(Vector3.Transform(b, xform), Vector3.Normalize(Vector3.TransformNormal(b, xform)));
|
|
|
- var cc = new VPOSNRM(Vector3.Transform(c, xform), Vector3.Normalize(Vector3.TransformNormal(c, xform)));
|
|
|
+ var tt = (a + b + c) / 3.0f;
|
|
|
|
|
|
- meshBuilder.UsePrimitive(material).AddTriangle(aa, bb, cc);
|
|
|
+ var aa = _CreateVertex(a, xform);
|
|
|
+ var bb = _CreateVertex(b, xform);
|
|
|
+ var cc = _CreateVertex(c, xform);
|
|
|
+ primitiveBuilder.AddTriangle(aa, bb, cc);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -114,22 +182,53 @@ namespace SharpGLTF.Schema2.Authoring
|
|
|
var ca = Vector3.Normalize(c + a) * c.Length();
|
|
|
|
|
|
// central triangle
|
|
|
- _AddSphereTriangle(meshBuilder, material, xform, ab, bc, ca, iterations);
|
|
|
+ _AddSphereFace(primitiveBuilder, xform, ab, bc, ca, iterations);
|
|
|
|
|
|
// vertex triangles
|
|
|
- _AddSphereTriangle(meshBuilder, material, xform, a, ab, ca, iterations);
|
|
|
- _AddSphereTriangle(meshBuilder, material, xform, b, bc, ab, iterations);
|
|
|
- _AddSphereTriangle(meshBuilder, material, xform, c, ca, bc, iterations);
|
|
|
+ _AddSphereFace(primitiveBuilder, xform, a, ab, ca, iterations);
|
|
|
+ _AddSphereFace(primitiveBuilder, xform, b, bc, ab, iterations);
|
|
|
+ _AddSphereFace(primitiveBuilder, xform, c, ca, bc, iterations);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static VERTEX _CreateVertex(Vector3 position, Matrix4x4 xform)
|
|
|
+ {
|
|
|
+ var v = new VERTEX();
|
|
|
+
|
|
|
+ v.Geometry.Position = Vector3.Transform(position, xform);
|
|
|
+ v.Geometry.Normal = Vector3.Normalize(Vector3.TransformNormal(position, xform));
|
|
|
+ v.Material.Color = Vector4.One;
|
|
|
+ v.Material.TexCoord = Vector2.Zero;
|
|
|
+
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+
|
|
|
+ static class SolidMeshUtils
|
|
|
+ {
|
|
|
+ public static void AddCube<TMaterial>(this IMeshBuilder<TMaterial> meshBuilder, TMaterial material, Matrix4x4 xform)
|
|
|
+ {
|
|
|
+ var cube = new Cube<TMaterial>(material);
|
|
|
+
|
|
|
+ cube.AddTo(meshBuilder, xform);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void AddSphere<TMaterial>(this IMeshBuilder<TMaterial> meshBuilder, TMaterial material, Single radius, Matrix4x4 xform)
|
|
|
+ {
|
|
|
+ var sphere = new IcoSphere<TMaterial>(material, radius);
|
|
|
+
|
|
|
+ sphere.AddTo(meshBuilder, xform);
|
|
|
}
|
|
|
|
|
|
- public static MeshBuilder<VPOS, VTEX1> CreateTerrainMesh(int width, int length, Func<int,int,float> heightFunction, string terrainColorImagePath)
|
|
|
+ public static MeshBuilder<VertexPosition, VertexTexture1> CreateTerrainMesh(int width, int length, Func<int,int,float> heightFunction, string terrainColorImagePath)
|
|
|
{
|
|
|
// we create a new material to use with the terrain mesh
|
|
|
var material = new Materials.MaterialBuilder("TerrainMaterial")
|
|
|
.WithChannelImage(Materials.KnownChannels.BaseColor, terrainColorImagePath);
|
|
|
|
|
|
// we create a MeshBuilder
|
|
|
- var terrainMesh = new MeshBuilder<VPOS, VTEX1>("terrain");
|
|
|
+ var terrainMesh = new MeshBuilder<VertexPosition, VertexTexture1>("terrain");
|
|
|
|
|
|
var texScale = new Vector2(width, length);
|
|
|
|