コード例 #1
0
    private void SampleFunction(GridSample grid)
    {
        float z = 0;
        int   i = 0;

        for (; i < numberOfBalls; ++i)
        {
            Metaball ball = _metaballs[i];
            float    x2   = grid.x - ball.position.x;
            float    y2   = grid.y - ball.position.y;

            z += (ball.radius * ball.radius) / ((x2 * x2) + (y2 * y2));
        }

        grid.sample = z;
    }
コード例 #2
0
ファイル: MetaballsMesh.cs プロジェクト: vnmone/vvvv-sdk
        private Mesh CreateMesh(Metaball metaball, Device device)
        {
            var mesh = new Mesh(
                device,
                NumIndices / 3,
                NumVertices,
                MeshFlags.Dynamic | MeshFlags.WriteOnly,
                VertexFormat.PositionNormal
                );

            // lock buffers
            sVx = mesh.LockVertexBuffer(LockFlags.Discard);
            sIx = mesh.LockIndexBuffer(LockFlags.Discard);
            try
            {
                // write buffers
                unsafe
                {
                    fixed(sVxBuffer *FixTemp = &VxBuffer[0])
                    {
                        IntPtr VxPointer = new IntPtr(FixTemp);

                        sVx.WriteRange(VxPointer, sizeof(sVxBuffer) * NumVertices);
                    }
                    fixed(short *FixTemp = &IxBuffer[0])
                    {
                        IntPtr IxPointer = new IntPtr(FixTemp);

                        sIx.WriteRange(IxPointer, sizeof(short) * NumIndices);
                    }
                }
            }
            finally
            {
                // unlock buffers
                mesh.UnlockIndexBuffer();
                mesh.UnlockVertexBuffer();
            }
            return(mesh);
        }
コード例 #3
0
    private void GenerateMetaballs()
    {
        metaballs = new Metaball[metaballCount];

        for (int i = 0; i < metaballCount; i++)
        {
            Metaball m = new Metaball();
            m.position = new Vector3();
//            m.position.x = Random.Range(0, size);
//            m.position.y = Random.Range(0, size);
            m.position.x = size * 0.5f;
            m.position.y = size * 0.5f;
            m.radius     = Random.Range(Mathf.Min(minSize, maxSize), Mathf.Max(minSize, maxSize));
            m.color      = Random.ColorHSV(0f, 1f, 0.8f, 1f, 0.1f, 1f);
            m.velocity   = Random.onUnitSphere * maxVelocity * 2f;
            m.velocity.z = 0;

            ClampVelocity(m);

            metaballs[i] = m;
        }
    }
コード例 #4
0
ファイル: MetaballGrid.cs プロジェクト: cozlind/metaballs
    public void evaluateAll()
    {
        if (metaballs == null)
        {
            return;
        }

        if (!initialized)
        {
            init();
        }

        // write info about metaballs in format readable by compute shaders
        gpuBalls = new GPUBall[metaballs.Length];
        for (int i = 0; i < metaballs.Length; i++)
        {
            Metaball metaball = metaballs[i];
            gpuBalls[i].position = metaballRenderer.transform.localToWorldMatrix.inverse.MultiplyPoint3x4(metaball.transform.position);
            gpuBalls[i].factor   = metaball.factor / Mathf.Pow(((metaballRenderer.transform.lossyScale.x + metaballRenderer.transform.lossyScale.y + metaballRenderer.transform.lossyScale.z) / 3.0f), 2.0f);
        }

        runComputeShader(gpuBalls);
    }
コード例 #5
0
    private void ClampVelocity2(Metaball m)
    {
        if (m.position.x + m.radius >= bounds.max.x)
        {
            m.velocity   = -m.velocity;
            m.position.x = bounds.max.x - m.radius;
        }
        else if (m.position.x - m.radius <= bounds.min.x)
        {
            m.velocity   = -m.velocity;
            m.position.x = bounds.min.x + m.radius;
        }

        if (m.position.y + m.radius >= bounds.max.y)
        {
            m.velocity   = -m.velocity;
            m.position.y = bounds.max.y - m.radius;
        }
        else if (m.position.y - m.radius <= bounds.min.y)
        {
            m.velocity   = -m.velocity;
            m.position.y = bounds.min.y + m.radius;
        }
    }
コード例 #6
0
    protected void Update()
    {
        // update ball positions
        int i = 0;

        for (; i < numberOfBalls; ++i)
        {
            Metaball ball = _metaballs[i];
            ball.position += ball.velocity * Time.deltaTime;

            if (ball.position.x > bounds.xMax || ball.position.x < bounds.xMin)
            {
                ball.velocity.x = -ball.velocity.x;
            }
            if (ball.position.y > bounds.yMax || ball.position.y < bounds.yMin)
            {
                ball.velocity.y = -ball.velocity.y;
            }
        }

        // update grid samples for new metaball positions
        int l = _grid.Length;

        for (i = 0; i < l; ++i)
        {
            SampleFunction(_grid[i]);
        }

        // build mesh from grid samples
        int vi = 0, ti = 0;

        for (i = 0; i < l; ++i)
        {
            GridSample grid = _grid[i];

            float sampleA = grid.sample;
            float sampleB = _grid[grid.iB].sample;
            float sampleC = _grid[grid.iC].sample;
            float sampleD = _grid[grid.iD].sample;

            // get the index value for this grid position
            int index = IndexFunction(sampleA, sampleB, sampleD, sampleC);
            if (index > 0 && index < 15)
            {
                // populate vertext and triangle buffers for this grid position
                Vector3 p = new Vector3(grid.x, grid.y, 0);

                Vector3[] points = MetaballDefs.pointLookupTable[index];
                int[]     triangles = MetaballDefs.triangleLookupTable[index];
                int       j = 0, k = triangles.Length;
                for (j = 0; j < k; j += 3)
                {
                    int t1 = triangles[j];
                    int t2 = triangles[j + 1];
                    int t3 = triangles[j + 2];

                    Vector3 p0 = points[t1];
                    Vector3 p1 = points[t2];
                    Vector3 p2 = points[t3];

                    // use SmoothFunction to Lerp points based on sample values
                    p0 = SmoothFunction(p0, sampleA, sampleB, sampleC, sampleD);
                    p1 = SmoothFunction(p1, sampleA, sampleB, sampleC, sampleD);
                    p2 = SmoothFunction(p2, sampleA, sampleB, sampleC, sampleD);

                    _vertices[vi]     = p + (p0 * _gridSize);
                    _vertices[vi + 1] = p + (p1 * _gridSize);
                    _vertices[vi + 2] = p + (p2 * _gridSize);

                    _triangles[ti]     = vi;
                    _triangles[ti + 1] = vi + 1;
                    _triangles[ti + 2] = vi + 2;

                    vi += 3;
                    ti += 3;
                }
            }
            else if (index == 15)
            {
                Vector3   p = new Vector3(grid.x, grid.y, 0);
                Vector3[] points = MetaballDefs.pointLookupTable[index];
                int[]     triangles = MetaballDefs.triangleLookupTable[index];
                int       j = 0, k = triangles.Length;
                for (j = 0; j < k; j += 3)
                {
                    Vector3 p0 = points[triangles[j]];
                    Vector3 p1 = points[triangles[j + 1]];
                    Vector3 p2 = points[triangles[j + 2]];

                    _vertices[vi]     = p + (p0 * _gridSize);
                    _vertices[vi + 1] = p + (p1 * _gridSize);
                    _vertices[vi + 2] = p + (p2 * _gridSize);

                    _triangles[ti]     = vi;
                    _triangles[ti + 1] = vi + 1;
                    _triangles[ti + 2] = vi + 2;

                    vi += 3;
                    ti += 3;
                }
            }
        }

        // clear unused portion of vertex and triangle buffers
        System.Array.Clear(_vertices, vi, _verticesLength - vi);
        System.Array.Clear(_triangles, ti, _trianglesLength - ti);

        // update mesh
        _mesh.Clear(false);
        _mesh.vertices  = _vertices;
        _mesh.triangles = _triangles;
    }
コード例 #7
0
ファイル: AtomMetaballs.cs プロジェクト: carlhuth/GenXSource
        public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs,
                                                      GeomDataBufferStream geomStream, int stream,
                                                      ref BufferedGeometryData buffer, CompleteOutputDescription coDesc)
        {
            // fillable fields
            int positionPos = -1;
            int normalPos   = -1;
            int diffusePos  = -1;

            // match field locations
            for (int i = 0; i < fields.Length; i++)
            {
                for (int gf = 0; gf < geomStream.Fields.Length; gf++)
                {
                    if (fields[i].Format == geomStream.Fields[gf])
                    {
                        if (fields[i].Usage == "POSITION")
                        {
                            positionPos = geomStream.FieldPositions[gf];
                        }
                        else if (fields[i].Usage == "NORMAL")
                        {
                            normalPos = geomStream.FieldPositions[gf];
                        }
                        else if (fields[i].Usage == "DIFFUSE")
                        {
                            diffusePos = geomStream.FieldPositions[gf];
                        }
                        break;
                    }
                }
            }

            // actually create the metaball triangles or points
            IVolume[]               volumes  = new IVolume[objs.Count];
            int                     sIdx     = 0;
            AtomShadingDesc         aShading = coDesc.AtomShadingDesc;
            IMoleculeMaterialLookup lookup   = aShading.MoleculeMaterials;

            foreach (IAtom atom in objs)
            {
                IMoleculeMaterialTemplate matTemp  = lookup.ResolveBySymbol(atom.Symbol);
                IMoleculeMaterial         material = null;
                if (matTemp != null)
                {
                    material = matTemp.BySymbol;
                }
                else
                {
                    PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"];
                    if (pe != null)
                    {
                        material = lookup.GetBySeries(pe.ChemicalSerie);
                    }
                }

                volumes[sIdx++] = new Metaball(new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d), 0.17f, material.BaseColor);
            }

            // process volume into triangles
            GenericVolumeScene scene = new GenericVolumeScene(volumes);

            int[]     triangles = null;
            Vector3[] vertices;
            Color[]   colours;
            Vector3[] normals = null;

            if (!pointsOnly)
            {
                IsosurfaceGenerator3D.GenerateSimpleMesh(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, false, out triangles, out vertices, out colours);
                MeshOptimzer.GenerateTriPointNormals(triangles, vertices, out normals);
            }
            else
            {
                IsosurfaceGenerator3D.GenerateSimplePointOutline(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, out vertices, out colours);
            }

            // create buffers
            buffer                    = new BufferedGeometryData(device, objs.Count);
            buffer.vBuffers           = new BufferedGeometryData.VertexData[1];
            buffer.vBuffers[0]        = new BufferedGeometryData.VertexData();
            buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * vertices.Length,
                                                         Usage.WriteOnly, geomStream.Format, Pool.Managed);
            buffer.vBuffers[0].Stride      = geomStream.Stride;
            buffer.vBuffers[0].NumElements = vertices.Length;
            buffer.vBuffers[0].Format      = geomStream.Format;

            buffer.iBuffers         = new BufferedGeometryData.IndexData[1];
            buffer.iBuffers[0]      = new BufferedGeometryData.IndexData();
            buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry;
            if (pointsOnly)
            {
                buffer.iBuffers[0].NumPrimitives = vertices.Length;
                buffer.iBuffers[0].PrimType      = PrimitiveType.PointList;
                buffer.Light = false;
            }
            else
            {
                buffer.iBuffers[0].NumPrimitives = triangles.Length / 3;
                buffer.iBuffers[0].PrimType      = PrimitiveType.TriangleList;
                buffer.iBuffers[0].Buffer        = new IndexBuffer(typeof(int), triangles.Length, device, Usage.WriteOnly, Pool.Managed);
            }

            // lock stream
            GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None);

            // fill fields

            int  clr = Color.FromArgb(255, 255, 255).ToArgb();
            long pos = 0;

            for (int i = 0; i < vertices.Length; i++)
            {
                if (positionPos != -1)
                {
                    data.Seek(pos + positionPos, SeekOrigin.Begin);
                    data.Write(vertices[i].X);
                    data.Write(vertices[i].Y);
                    data.Write(vertices[i].Z);
                }
                if (normalPos != -1 && !pointsOnly)
                {
                    data.Seek(pos + normalPos, SeekOrigin.Begin);
                    data.Write(normals[i].X);
                    data.Write(normals[i].Y);
                    data.Write(normals[i].Z);
                }
                if (diffusePos != -1)
                {
                    data.Seek(pos + diffusePos, SeekOrigin.Begin);
                    data.Write(colours[i].ToArgb());
                }
                //verts[i].Color = colours[i].ToArgb();
                pos += geomStream.Stride;
            }

            buffer.vBuffers[0].Buffer.Unlock();

            if (!pointsOnly)
            {
                buffer.iBuffers[0].Buffer.SetData(triangles, 0, LockFlags.None);
            }

            // dispose of temp data
        }
コード例 #8
0
    /**This function should generate the mesh that surrounds all of the metaballs.
     * Although there may be many metaballs, it will technically only generate a single mesh. **/

    void generateMesh()
    {
        if (metaballs.Count <= 0)
        {
            return;
        }
        //STEP 1. Iterate through the cubic region surrounding each metaball.
        //Determine the largest size of the region to explore. Need to locate the largest and smallest X, Y and Z values.
        vertices.Clear();
        triangles.Clear();
        float minX, maxX, minY, maxY, minZ, maxZ;

        minX = maxX = minY = maxY = minZ = maxZ = 0;

        for (int i = 0; i < metaballs.Count; i++)
        {
            Metaball m        = metaballs[i];
            Vector3  position = m.transform.position;
            float    r        = m.maxSquaredRadius;
            if ((i == 0) || (position.x - r < minX))
            {
                minX = position.x - r;
            }
            if ((i == 0) || (position.x + r > maxX))
            {
                maxX = position.x + r;
            }
            if ((i == 0) || (position.y - r < minY))
            {
                minY = position.y - r;
            }
            if ((i == 0) || (position.y + r > maxY))
            {
                maxY = position.y + r;
            }
            if ((i == 0) || (position.z - r < minZ))
            {
                minZ = position.z - r;
            }
            if ((i == 0) || (position.z + r > maxZ))
            {
                maxZ = position.z + r;
            }
        }
        int     xResolution = Mathf.CeilToInt((maxX - minX) / cubeLength);
        int     yResolution = Mathf.CeilToInt((maxY - minY) / cubeLength);
        int     zResolution = Mathf.CeilToInt((maxZ - minZ) / cubeLength);
        Vector3 corner      = new Vector3(minX, minY, minZ);

        for (int x = 0; x < xResolution; x++)
        {
            for (int y = 0; y < yResolution; y++)
            {
                for (int z = 0; z < zResolution; z++)
                {
                    //Start in left, bottom, back corner, slowly work your way to the right, top, front corner.
                    //For each cube you will examine 8 points, and determine the value at that point
                    //Each cube is going to need 8 vertices - Order is strange because it needs to fit with the Marching Cubes library
                    //1. Left Bottom Back
                    int     i    = (x * xResolution * xResolution) + (y * yResolution) + z;
                    float[] cube = new float[8];
                    cube[0] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * z)));
                    //2. Left Bottom Front
                    cube[4] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * (z + 1))));
                    //3. Left Top Back
                    cube[3] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * z)));
                    //4. Left Top Front
                    cube[7] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * (z + 1))));
                    //5. Right Bottom Back
                    cube[1] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * y), corner.z + (cubeLength * z)));
                    //6. Right Bottom Front
                    cube[5] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * y), corner.z + (cubeLength * (z + 1))));
                    //7. Right Top Back
                    cube[2] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * z)));
                    //8. Right Top Front
                    cube[6] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * (z + 1))));
                    marching.March(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * z), cube, cubeLength, vertices, triangles);
                }
            }
        }
        mesh.Clear();
        mesh.vertices  = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.RecalculateNormals();
    }