Пример #1
0
        /// <summary>
        /// Creates the cornell box.
        /// </summary>
        /// <param name="roomSize">Size of the room.</param>
        /// <param name="sphereRadius">The sphere radius.</param>
        /// <param name="cubeSize">Size of the cube.</param>
        /// <returns></returns>
        public static DefaultMesh CreateCornellBox(float roomSize = 2, float sphereRadius = 0.3f, float cubeSize = 0.6f)
        {
            var mesh = new DefaultMesh();
            //off-center plane
            var plane = CreatePlane(roomSize, roomSize, 2, 2).Transform(Transformation.Translation(0, -roomSize / 2, 0));

            plane.SetConstantUV(new Vector2(0, 0));
            mesh.Add(plane);                                                  //bottom
                                                                              //rotate plane repeatedly to create box
            mesh.Add(plane.Transform(Transformation.Rotation(90f, Axis.X)));  //front
            mesh.Add(plane.Transform(Transformation.Rotation(-90f, Axis.X))); //back
            plane.SetConstantUV(new Vector2(1, 0));
            mesh.Add(plane.Transform(Transformation.Rotation(90f, Axis.Z)));  //right
            plane.SetConstantUV(new Vector2(2, 0));
            mesh.Add(plane.Transform(Transformation.Rotation(270f, Axis.Z))); //left
            plane.SetConstantUV(new Vector2(0, 0));
            mesh.Add(plane.Transform(Transformation.Rotation(180f, Axis.Z))); //top

            var sphere = CreateSphere(sphereRadius, 4);

            sphere.SetConstantUV(new Vector2(3, 0));
            mesh.Add(sphere.Transform(Transformation.Translation(0.4f, -1 + sphereRadius, -0.2f)));

            var cube             = CreateCubeWithNormals(cubeSize);
            var translateAndRotY = Transformation.Combine(Transformation.Rotation(35f, Axis.Y), Transformation.Translation(-0.5f, -1 + 0.5f * cubeSize, 0.1f));

            cube.SetConstantUV(new Vector2(3, 0));
            mesh.Add(cube.Transform(translateAndRotY));
            return(mesh);
        }
Пример #2
0
        /// <summary>
        /// Adds the specified b.
        /// </summary>
        /// <param name="a">a.</param>
        /// <param name="b">The b.</param>
        /// <exception cref="ArgumentException">Original mesh has no normals, but added mesh has normals
        /// or
        /// Original mesh has no uvs, but added mesh has uvs</exception>
        public static void Add(this DefaultMesh a, DefaultMesh b)
        {
            var count = (uint)a.Position.Count;

            a.Position.AddRange(b.Position);
            if (b.Normal.Count > 0)
            {
                if (a.Normal.Count != count)
                {
                    throw new ArgumentException("Original mesh has no normals, but added mesh has normals");
                }
                a.Normal.AddRange(b.Normal);
            }
            if (b.TexCoord.Count > 0)
            {
                if (a.TexCoord.Count != count)
                {
                    throw new ArgumentException("Original mesh has no uvs, but added mesh has uvs");
                }
                a.TexCoord.AddRange(b.TexCoord);
            }
            foreach (var id in b.IDs)
            {
                a.IDs.Add(id + count);
            }
        }
Пример #3
0
        /// <summary>
        /// Creates a cube made up of pairs of triangles; stored as an indexed vertex array
        /// </summary>
        /// <param name="size">length of one side</param>
        /// <returns>
        /// Mesh with positions, ids, normals
        /// </returns>
        public static DefaultMesh CreateCubeWithNormals(float size = 1.0f)
        {
            var m = new DefaultMesh();

            void createPosition(float x, float y, float z) => m.Position.Add(new Vector3(x, y, z));
            void createID(uint index) => m.IDs.Add(index);
            void createNormal(float x, float y, float z) => m.Normal.Add(new Vector3(x, y, z));

            ShapeBuilder.Cube(createPosition, createID, size, createNormal);
            return(m);
        }
Пример #4
0
        /// <summary>
        /// creates a sphere made up of pairs of triangles; stored as an indexed vertex array
        /// </summary>
        /// <param name="radius">radius</param>
        /// <param name="subdivision">subdivision count, each subdivision creates 4 times more faces</param>
        /// <returns>
        /// Mesh with positions, ids, normals
        /// </returns>
        public static DefaultMesh CreateSphere(float radius = 1.0f, uint subdivision = 1)
        {
            var m = new DefaultMesh();

            //var pos = m.AddAttribute<Vector3>(Mesh.PositionName);
            //var normal = m.AddAttribute<Vector3>(Mesh.NormalName);
            void createPosition(float x, float y, float z) => m.Position.Add(new Vector3(x, y, z));
            void createID(uint id) => m.IDs.Add(id);
            void createNormal(float x, float y, float z) => m.Normal.Add(new Vector3(x, y, z));

            ShapeBuilder.Sphere(createPosition, createID, radius, subdivision, createNormal);
            return(m);
        }
Пример #5
0
        /// <summary>
        /// Flips the normals.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <returns></returns>
        public static DefaultMesh FlipNormals(this DefaultMesh m)
        {
            var mesh = new DefaultMesh();

            mesh.Position.AddRange(m.Position);
            mesh.TexCoord.AddRange(m.TexCoord);
            mesh.IDs.AddRange(m.IDs);
            foreach (var n in m.Normal)
            {
                var newN = -n;
                mesh.Normal.Add(newN);
            }
            return(mesh);
        }
Пример #6
0
        /// <summary>
        /// Switches the triangle mesh winding.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <returns></returns>
        public static DefaultMesh SwitchTriangleMeshWinding(this DefaultMesh m)
        {
            var mesh = new DefaultMesh();

            mesh.Position.AddRange(m.Position);
            mesh.Normal.AddRange(m.Normal);
            mesh.TexCoord.AddRange(m.TexCoord);
            for (int i = 0; i < m.IDs.Count; i += 3)
            {
                mesh.IDs.Add(m.IDs[i]);
                mesh.IDs.Add(m.IDs[i + 2]);
                mesh.IDs.Add(m.IDs[i + 1]);
            }
            return(mesh);
        }
Пример #7
0
        /// <summary>
        /// Creates a plane made up of pairs of triangles; stored as an indexed vertex array.
        /// </summary>
        /// <param name="sizeX">extent of the grid in the x-coordinate axis</param>
        /// <param name="sizeZ">extent of the grid in the z-coordinate axis</param>
        /// <param name="segmentsX">number of grid segments in the x-coordinate axis</param>
        /// <param name="segmentsZ">number of grid segments in the z-coordinate axis</param>
        /// <returns>
        /// Mesh with positions, ids, normals, and uvs
        /// </returns>
        public static DefaultMesh CreatePlane(float sizeX, float sizeZ, uint segmentsX, uint segmentsZ)
        {
            var m = new DefaultMesh();

            void CreateVertex(float x, float z) => m.Position.Add(new Vector3(x, 0.0f, z));
            void CreateID(uint id) => m.IDs.Add(id);
            void CreateNormal() => m.Normal.Add(Vector3.UnitY);
            void CreateUV(float u, float v) => m.TexCoord.Add(new Vector2(u, v));

            var startX = -sizeX / 2f;
            var startZ = -sizeZ / 2f;

            ShapeBuilder.Grid(startX, sizeX, startZ, sizeZ, segmentsX, segmentsZ, CreateVertex, CreateID
                              , CreateNormal, CreateUV);
            return(m);
        }
Пример #8
0
        /// <summary>
        /// Sets the constant uv.
        /// </summary>
        /// <param name="mesh">The mesh.</param>
        /// <param name="uv">The uv.</param>
        public static void SetConstantUV(this DefaultMesh mesh, Vector2 uv)
        {
            var uvs = mesh.TexCoord;
            var pos = mesh.Position;

            uvs.Capacity = pos.Count;
            //overwrite existing
            for (int i = 0; i < uvs.Count; ++i)
            {
                uvs[i] = uv;
            }
            //add
            for (int i = uvs.Count; i < pos.Count; ++i)
            {
                uvs.Add(uv);
            }
        }
Пример #9
0
        /// <summary>
        /// Transforms the mesh by the specified transform.
        /// </summary>
        /// <param name="mesh">The mesh to transform.</param>
        /// <param name="transformation">The transformation.</param>
        /// <returns></returns>
        public static DefaultMesh Transform(this DefaultMesh mesh, Transformation transformation)
        {
            var newMesh = new DefaultMesh();

            newMesh.TexCoord.AddRange(mesh.TexCoord);
            newMesh.IDs.AddRange(mesh.IDs);
            foreach (var pos in mesh.Position)
            {
                var newPos = transformation.Transform(pos);
                newMesh.Position.Add(newPos);
            }
            foreach (var n in mesh.Normal)
            {
                var newN = Vector3.Normalize(Vector3.TransformNormal(n, transformation.Matrix));
                newMesh.Normal.Add(newN);
            }
            return(newMesh);
        }
Пример #10
0
        /// <summary>
        /// Transforms the specified transform.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <param name="transform">The transform.</param>
        /// <returns></returns>
        public static DefaultMesh Transform(this DefaultMesh m, Matrix4x4 transform)
        {
            var mesh = new DefaultMesh();

            mesh.TexCoord.AddRange(m.TexCoord);
            mesh.IDs.AddRange(m.IDs);
            foreach (var pos in m.Position)
            {
                var newPos = Vector3.Transform(pos, transform);
                mesh.Position.Add(newPos);
            }
            foreach (var n in m.Normal)
            {
                var newN = Vector3.Normalize(Vector3.TransformNormal(n, transform));
                mesh.Normal.Add(newN);
            }
            return(mesh);
        }
Пример #11
0
        /// <summary>
        /// Switches the handedness.
        /// </summary>
        /// <param name="m">The m.</param>
        /// <returns></returns>
        public static DefaultMesh SwitchHandedness(this DefaultMesh m)
        {
            var mesh = new DefaultMesh();

            mesh.TexCoord.AddRange(m.TexCoord);
            mesh.IDs.AddRange(m.IDs);
            foreach (var pos in m.Position)
            {
                var newPos = pos;
                newPos.Z = -newPos.Z;
                mesh.Position.Add(newPos);
            }
            foreach (var n in m.Normal)
            {
                var newN = n;
                newN.Z = -newN.Z;
                mesh.Normal.Add(newN);
            }
            return(mesh);
        }
Пример #12
0
        /// <summary>
        /// Creates a <see cref="DefaultMesh"/>from a byte array.
        /// </summary>
        /// <param name="objByteData">The byte data.</param>
        /// <returns></returns>
        public static DefaultMesh FromObj(byte[] objByteData)
        {
            var parser          = new ObjParser(new MemoryStream(objByteData));
            var uniqueVertexIDs = new Dictionary <ObjParser.Vertex, uint>(new VertexComparer());

            var mesh = new DefaultMesh();

            foreach (var face in parser.faces)
            {
                //only accept triangles
                if (3 != face.Count)
                {
                    continue;
                }
                foreach (var vertex in face)
                {
                    if (uniqueVertexIDs.TryGetValue(vertex, out uint index))
                    {
                        mesh.IDs.Add(index);
                    }
                    else
                    {
                        uint id = (uint)mesh.Position.Count;
                        //add vertex data to mesh
                        mesh.Position.Add(parser.position[vertex.idPos]);
                        if (-1 != vertex.idNormal)
                        {
                            mesh.Normal.Add(parser.normals[vertex.idNormal]);
                        }
                        if (-1 != vertex.idTexCoord)
                        {
                            mesh.TexCoord.Add(parser.texCoords[vertex.idTexCoord]);
                        }
                        mesh.IDs.Add(id);
                        //new id
                        uniqueVertexIDs[vertex] = id;
                    }
                }
            }
            return(mesh);
        }
Пример #13
0
        /// <summary>
        /// Creates the cornell box.
        /// </summary>
        /// <param name="roomSize">Size of the room.</param>
        /// <param name="sphereRadius">The sphere radius.</param>
        /// <param name="cubeSize">Size of the cube.</param>
        /// <returns></returns>
        public static DefaultMesh CreateCornellBox(float roomSize = 2, float sphereRadius = 0.3f, float cubeSize = 0.6f)
        {
            var mesh  = new DefaultMesh();
            var plane = CreatePlane(roomSize, roomSize, 2, 2);

            var xform = new Transformation();

            xform.TranslateGlobal(0, -roomSize / 2, 0);
            plane.SetConstantUV(new Vector2(3, 0));
            mesh.Add(plane.Transform(xform));
            xform.RotateZGlobal(90f);
            plane.SetConstantUV(new Vector2(1, 0));
            mesh.Add(plane.Transform(xform));
            xform.RotateZGlobal(90f);
            plane.SetConstantUV(new Vector2(0, 0));
            mesh.Add(plane.Transform(xform));
            xform.RotateZGlobal(90f);
            plane.SetConstantUV(new Vector2(2, 0));
            mesh.Add(plane.Transform(xform));
            xform.RotateYGlobal(270f);
            plane.SetConstantUV(new Vector2(0, 0));
            mesh.Add(plane.Transform(xform));

            var sphere = Meshes.CreateSphere(sphereRadius, 4);

            sphere.SetConstantUV(new Vector2(3, 0));
            xform.Reset();
            xform.TranslateGlobal(0.4f, -1 + sphereRadius, -0.2f);
            mesh.Add(sphere.Transform(xform));

            var cube = Meshes.CreateCubeWithNormals(cubeSize);

            cube.SetConstantUV(new Vector2(3, 0));
            xform.Reset();
            xform.RotateYGlobal(35f);
            xform.TranslateGlobal(-0.5f, -1 + 0.5f * cubeSize, 0.1f);
            mesh.Add(cube.Transform(xform));
            return(mesh);
        }
Пример #14
0
        /// <summary>
        /// Transforms the mesh by the specified transform.
        /// </summary>
        /// <param name="mesh">The mesh to transform.</param>
        /// <param name="transform">The transformation.</param>
        /// <returns></returns>
        public static DefaultMesh Transform(this DefaultMesh mesh, Transformation3D transform)
        {
            if (transform is null)
            {
                throw new ArgumentNullException(nameof(transform));
            }
            var matrix  = transform.CalcLocalToWorldRowMajorMatrix();
            var newMesh = new DefaultMesh();

            newMesh.TexCoord.AddRange(mesh.TexCoord);
            newMesh.IDs.AddRange(mesh.IDs);
            foreach (var pos in mesh.Position)
            {
                var newPos = Vector3.Transform(pos, matrix);
                newMesh.Position.Add(newPos);
            }
            foreach (var n in mesh.Normal)
            {
                var newN = Vector3.Normalize(Vector3.TransformNormal(n, matrix));
                newMesh.Normal.Add(newN);
            }
            return(newMesh);
        }
Пример #15
0
 /// <summary>
 /// Sets the constant uv.
 /// </summary>
 /// <param name="mesh">The mesh.</param>
 /// <param name="uv">The uv.</param>
 public static void SetConstantUV(this DefaultMesh mesh, in Vector2 uv)