Ejemplo n.º 1
0
        private static void ParseFromFile(ResourceFile file, UnsafeBufferWriter <Vertex> verticesBuffer, UnsafeBufferWriter <int> indicesBuffer)
        {
            using var stream = file.GetStream();
            using var obj    = ObjParser.ParseUnsafe(stream);

            var hasUV = !obj.UVIndices.IsEmpty;

            using var uvIndicesBuf = hasUV ? UnsafeRawArray <int> .Empty : new UnsafeRawArray <int>(obj.PositionIndices.Length, true);
            var uvs = hasUV ? obj.UVs : stackalloc Vector2[1] {
                Vector2.Zero
            };
            var uvIndices = hasUV ? obj.UVIndices : uvIndicesBuf.AsSpan();

            var hasNormal = !obj.NormalIndices.IsEmpty;

            if (hasNormal == false)
            {
                using var normalsBuf = new UnsafeBufferWriter <Vector3>();
                var positions        = obj.Positions;
                var posNormalIndices = obj.PositionIndices;
                var normals          = MeshOperations.RecalculateNormal(positions, posNormalIndices, normalsBuf);
                MeshOperations.CreateInterleavedVertices(positions, posNormalIndices, normals, posNormalIndices, uvs, uvIndices, verticesBuffer, indicesBuffer);
            }
            else
            {
                MeshOperations.CreateInterleavedVertices(obj.Positions, obj.PositionIndices, obj.Normals, obj.NormalIndices, uvs, uvIndices, verticesBuffer, indicesBuffer);
            }
        }
Ejemplo n.º 2
0
    public void UpdateGrainProperties()
    {
        Mesh mesh = gameObject.GetComponent <MeshFilter>().mesh;

        grainVolume = MeshOperations.VolumeOfMesh(mesh, scale);
        //grainSurfaceArea = MeshOperations.GetMeshSurfaceArea(mesh, scale);
        grainMass = grainDensity * grainVolume;
        gameObject.GetComponent <Rigidbody>().mass = grainMass;

        //Debug.Log("Mass " + grainMass);
        //Debug.Log("Volume " + grainVolume);
        //Debug.Log("Density " + grainDensity);
        //Debug.Log("SA " + grainSurfaceArea);
    }
Ejemplo n.º 3
0
    //===================================================================
    public float GetBestMultiplier(Mesh mesh, float volumeGoal, ResizeType resizeType)
    {
        MinMaxFloat minMaxRadius;
        float       initialDiameter = Mathf.Pow(3f / 4f / Mathf.PI * volumeGoal, 1f / 3f) * 2;

        //Debug.Log("initial Diameter" + initialDiameter);


        switch (resizeType)
        {
        // ================================
        case ResizeType.ByVolume:
            float minMultiplier    = .001f;
            float maxMultiplier    = 5f;
            float middleDiff       = 1f;
            float middleMultiplier = 0;

            while (middleDiff > .001)
            {
                middleMultiplier = (minMultiplier + maxMultiplier) / 2;
                float middleVolume = MeshOperations.VolumeOfMesh(mesh, middleMultiplier);
                middleDiff = Mathf.Abs(middleVolume - volumeGoal) / volumeGoal;

                if (middleVolume >= volumeGoal)
                {
                    maxMultiplier = middleMultiplier;
                }
                if (middleVolume < volumeGoal)
                {
                    minMultiplier = middleMultiplier;
                }
            }

            return(middleMultiplier);

        // ================================
        case ResizeType.ByRadiusIn:
            minMaxRadius = GetMinMaxRadius(mesh);
            return(initialDiameter / (minMaxRadius.max * 2));

        // ================================
        case ResizeType.ByRadiusOut:
            minMaxRadius = GetMinMaxRadius(mesh);
            return(initialDiameter / (minMaxRadius.min * 2));
        }

        return(1f);
    }
Ejemplo n.º 4
0
    //Amplitude = .05, Frequency = 1, Lacunarity = 2, OctaveCount = 6, Persistence = .5, ResizeType = ByVolume

    #endregion


    // Use this for initialization
    void Start()
    {
        // Create Perlin Noise
        PerlinNoiseOptions perlinOptions = GetPerlinNoiseOptions(amplitudeRange, frequencyRange, lacunarityRange, octaveCountRange, persistenceRange, seed);


        //Debug.Log(perlinOptions.amplitude);
        //Debug.Log(perlinOptions.frequency);
        //Debug.Log(perlinOptions.lacunarity);
        //Debug.Log(perlinOptions.octaveCount);
        //Debug.Log(perlinOptions.persistence);
        //Debug.Log(perlinOptions.seed);

        if (useRandomSeed == true)
        {
            perlinOptions.seed = Mathf.RoundToInt(Random.value * 1000000);
        }
        Perlin noise = new Perlin(perlinOptions.frequency, perlinOptions.lacunarity, perlinOptions.persistence, perlinOptions.octaveCount, seed, perlinOptions.quality);

        Mesh mesh = GetComponent <MeshFilter>().mesh;

        Vector3[] baseVertices = mesh.vertices;
        Vector3[] vertices     = new Vector3[baseVertices.Length];

        // get initial Mass and Volume
        float initialVolume = MeshOperations.VolumeOfMesh(mesh, 1);
        float initialMass   = gameObject.GetComponent <Rigidbody>().mass;

        var verticesCH = new Vertex[baseVertices.Length];

        // Apply Perlin Noise
        for (int i = 0; i < vertices.Length; i++)
        {
            var   vertex     = baseVertices[i] * 2;
            float noiseValue = (float)noise.GetValue(vertex.x, vertex.y, vertex.z);
            vertex       += vertex * noiseValue * perlinOptions.amplitude;
            vertices[i]   = vertex;
            verticesCH[i] = new Vertex((double)vertex.x, (double)vertex.y, (double)vertex.z);
        }

        // Convex Hull
        mesh = CreateConvexMesh(vertices);
        Vector3[] vertices2 = mesh.vertices;


        // Scale Mesh to Equal Sphere Volume
        float scaleMultiplier = GetBestMultiplier(mesh, initialVolume, resizeType);

        for (int i = 0; i < vertices2.Length; i++)
        {
            var vertex = vertices2[i];
            vertex      *= scaleMultiplier;
            vertices2[i] = vertex;
        }

        // Finalize Mesh
        mesh.vertices = vertices2;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        // Update Meshes
        GetComponent <MeshFilter>().mesh         = null;
        GetComponent <MeshFilter>().mesh         = mesh;
        GetComponent <MeshCollider>().sharedMesh = null;
        GetComponent <MeshCollider>().sharedMesh = mesh;

        // Update Mass
        gameObject.GetComponent <Rigidbody>().ResetCenterOfMass();
        UpdateGrainProperties();
    }
Ejemplo n.º 5
0
    //From triangle where each triangle has one vertex to half edge
    public static List <HalfEdge> TransformFromTriangleToHalfEdge(List <Triangle> triangles)
    {
        //Make sure the triangles have the same orientation
        MeshOperations.OrientTrianglesClockwise(triangles);

        //First create a list with all possible half-edges
        List <HalfEdge> halfEdges = new List <HalfEdge>(triangles.Count * 3);

        for (int i = 0; i < triangles.Count; i++)
        {
            Triangle t = triangles[i];

            HalfEdge he1 = new HalfEdge(t.v1);
            HalfEdge he2 = new HalfEdge(t.v2);
            HalfEdge he3 = new HalfEdge(t.v3);

            he1.nextEdge = he2;
            he2.nextEdge = he3;
            he3.nextEdge = he1;

            he1.prevEdge = he3;
            he2.prevEdge = he1;
            he3.prevEdge = he2;

            //The vertex needs to know of an edge going from it
            he1.v.halfEdge = he2;
            he2.v.halfEdge = he3;
            he3.v.halfEdge = he1;

            //The face the half-edge is connected to
            t.halfEdge = he1;

            he1.t = t;
            he2.t = t;
            he3.t = t;

            //Add the half-edges to the list
            halfEdges.Add(he1);
            halfEdges.Add(he2);
            halfEdges.Add(he3);
        }

        //Find the half-edges going in the opposite direction
        for (int i = 0; i < halfEdges.Count; i++)
        {
            HalfEdge he = halfEdges[i];

            Vertex goingToVertex   = he.v;
            Vertex goingFromVertex = he.prevEdge.v;

            for (int j = 0; j < halfEdges.Count; j++)
            {
                //Dont compare with itself
                if (i == j)
                {
                    continue;
                }

                HalfEdge heOpposite = halfEdges[j];

                //Is this edge going between the vertices in the opposite direction
                if (goingFromVertex.position == heOpposite.v.position && goingToVertex.position == heOpposite.prevEdge.v.position)
                {
                    he.oppositeEdge = heOpposite;

                    break;
                }
            }
        }


        return(halfEdges);
    }
Ejemplo n.º 6
0
        private ProjectedGeometry MeshToProjectedGeometry(MeshGeometry3D mesh, Transform3D tx)
        {
            MeshOperations.RemoveNullFields(mesh);

            if (mesh.TriangleIndices.Count == 0)
            {
                // Having triangle indices in a mesh isn't required
                // Generate them if they don't exist
                MeshOperations.GenerateTriangleIndices(mesh);
            }
            else
            {
                // If we didn't generate them, there could be bad indices in there.
                // Remove the triangles that would cause our renderer problems in the future.
                MeshOperations.RemoveBogusTriangles(mesh);
            }

            // Having texture coordinates in a mesh isn't required
            // Generate them if they don't exist
            if (mesh.TextureCoordinates.Count == 0)
            {
                MeshOperations.GenerateTextureCoordinates(mesh);
            }

            // We need explicit normal information, so calculate them when they're missing
            if (mesh.Normals.Count != mesh.Positions.Count)
            {
                // We default to counter-clockwise winding order ...
                MeshOperations.GenerateNormals(mesh, false);
            }

            Point3DCollection  positions          = mesh.Positions;
            Vector3DCollection normals            = mesh.Normals;
            PointCollection    textureCoordinates = mesh.TextureCoordinates;
            Int32Collection    triangleIndices    = mesh.TriangleIndices;

            // We think of the following coordinate systems:
            // Model space: Coordinates which are model-local
            // World space: Coordinates which relate all the models
            // Eye space: Coordinates where the eye point is (0,0,0) and is looking down -Z
            // Homogeneous space: Projected to a canonical rectangular solid view volume. (-1, -1, 0) -> (1, 1, 1)
            // Screen space: Scaled homogeneous space so that X,Y correspond to X,Y pixel values on the screen.
            Matrix3D modelToWorld      = tx.Value;
            Matrix3D worldToEye        = MatrixUtils.ViewMatrix(camera);
            Matrix3D modelToEyeMatrix  = modelToWorld * worldToEye;
            Matrix3D normalTransform   = MatrixUtils.MakeNormalTransform(modelToEyeMatrix);
            Matrix3D projectionMatrix  = MatrixUtils.ProjectionMatrix(camera);
            Matrix3D toScreenSpace     = MatrixUtils.HomogenousToScreenMatrix(bounds.ViewportBounds, camera is ProjectionCamera);
            Matrix3D projectToViewport = projectionMatrix * toScreenSpace;

            bool reverseWinding      = MatrixUtils.Determinant(modelToEyeMatrix) < 0;
            MeshProjectedGeometry pg = new MeshProjectedGeometry(projectToViewport);
            int numTriangles         = triangleIndices.Count / 3;

            Vertex v1, v2, v3;
            int    index;

            for (int n = 0; n < numTriangles; n++)
            {
                v1 = new Vertex();
                v2 = new Vertex();
                v3 = new Vertex();

                // We default material colors to pure White (0xff,0xff,0xff) since
                // we will iluminate against that and then modulate with
                // the actual textures on a per-pixel level.
                v1.Color = Colors.White;
                v2.Color = Colors.White;
                v3.Color = Colors.White;

                index = triangleIndices[n * 3];
                v1.ModelSpacePosition = positions[index];
                v1.ModelSpaceNormal   = normals[index];
                v1.Position           = MatrixUtils.Transform((Point4D)positions[index], modelToEyeMatrix);
                v1.Normal             = MatrixUtils.Transform(normals[index], normalTransform);
                v1.TextureCoordinates = textureCoordinates[index];

                index = triangleIndices[n * 3 + 1];
                v2.ModelSpacePosition = positions[index];
                v2.ModelSpaceNormal   = normals[index];
                v2.Position           = MatrixUtils.Transform((Point4D)positions[index], modelToEyeMatrix);
                v2.Normal             = MatrixUtils.Transform(normals[index], normalTransform);
                v2.TextureCoordinates = textureCoordinates[index];

                index = triangleIndices[n * 3 + 2];
                v3.ModelSpacePosition = positions[index];
                v3.ModelSpaceNormal   = normals[index];
                v3.Position           = MatrixUtils.Transform((Point4D)positions[index], modelToEyeMatrix);
                v3.Normal             = MatrixUtils.Transform(normals[index], normalTransform);
                v3.TextureCoordinates = textureCoordinates[index];

                if (reverseWinding)
                {
                    // Change winding-order so the mesh renders
                    pg.AddTriangle(v1, v3, v2);
                }
                else
                {
                    pg.AddTriangle(v1, v2, v3);
                }
            }

            pg.NormalizeTextureCoordinates();
            return(pg);
        }