Example #1
0
    // Call if base mesh changes
    public void ReStart()
    {
        mesh = MegaUtils.GetMesh(gameObject);

        if (mesh != null)
        {
            bbox   = mesh.bounds;
            sverts = new Vector3[mesh.vertexCount];
            verts  = mesh.vertices;

            uvs  = mesh.uv;
            suvs = new Vector2[mesh.uv.Length];
            cols = mesh.colors;

            mods = GetComponents <MegaModifier>();

            Array.Sort(mods, CompareOrder);

            for (int i = 0; i < mods.Length; i++)
            {
                if (mods[i] != null)
                {
                    mods[i].ModStart(this);                     // Some mods like push error if we dont do this, put in error check and disable
                }
            }
        }

        UpdateMesh = -1;
    }
    // ***************************************************************************
    // PS3 Code
    // ***************************************************************************
#if true        //UNITY_PS3
    void Awake()
    {
        if (Application.platform == RuntimePlatform.PS3 && !Application.isEditor)
        {
            Mesh ps3mesh = MegaUtils.GetMesh(gameObject);
            BuildPS3Mapping(verts, ps3mesh.vertices);
        }
    }
Example #3
0
    // Set the PS3 mesh vertices from the internal modified vertex array to the new ps3 vertex array
    public void SetPS3Mesh()
    {
        // This is here to test the remapping works in editor mode,
        // remove for use as Awake() will do this.
        if (ps3mapping == null || ps3mapping.Length == 0)
        {
            Mesh ps3mesh = MegaUtils.GetMesh(gameObject);
            BuildPS3Mapping(verts, ps3mesh.vertices);
        }

        if ((dirtyChannels & MegaModChannel.Verts) != 0)
        {
            for (int i = 0; i < sverts.Length; i++)
            {
                for (int m = 0; m < ps3mapping[i].indices.Length; m++)
                {
                    ps3verts[ps3mapping[i].indices[m]] = sverts[i];
                }
            }

            mesh.vertices = ps3verts;
        }

        if ((dirtyChannels & MegaModChannel.UV) != 0)
        {
            mesh.uv = suvs;
        }

        if (recalcnorms)
        {
            RecalcNormals();
        }

        if (recalcTangents)
        {
            BuildTangents();
        }

        if (recalcbounds)
        {
            mesh.RecalculateBounds();
        }

        if (recalcCollider)
        {
            if (meshCol == null)
            {
                meshCol = GetComponent <MeshCollider>();
            }

            if (meshCol != null)
            {
                meshCol.sharedMesh = null;
                meshCol.sharedMesh = mesh;
            }
        }
    }
Example #4
0
    // ***************************************************************************
    // PS3 Code
    // ***************************************************************************
#if true        //UNITY_PS3
    void Awake()
    {
#if UNITY_5_5 || UNITY_5_6 || UNITY_2017
#else
        if (Application.platform == RuntimePlatform.PS3 && !Application.isEditor)
        {
            Mesh ps3mesh = MegaUtils.GetMesh(gameObject);
            BuildPS3Mapping(verts, ps3mesh.vertices);
        }
#endif
    }
    public override bool Prepare(MegaModContext mc)
    {
        if (colmesh == null)
        {
            colmesh = new MegaColliderMesh();
        }

        if (colmesh.obj != hitObject && hitObject != null)
        {
            colmesh = new MegaColliderMesh();

            // This is colldier mesh not this mesh
            colmesh.mesh    = MegaUtils.GetMesh(hitObject);
            colmesh.verts   = colmesh.mesh.vertices;
            colmesh.tris    = colmesh.mesh.triangles;
            colmesh.normals = colmesh.mesh.normals;
            colmesh.obj     = hitObject;
        }

        if (hitObject)
        {
            //localPos = transform.worldToLocalMatrix.MultiplyPoint(hitObject.transform.position);
            col = hitObject.GetComponent <Collider>();
        }

        if (hitObject == null)
        {
            return(false);
        }

        affected.Clear();
        distances.Clear();

        if (offsets == null || offsets.Length != mc.mod.verts.Length)
        {
            offsets = new Vector3[mc.mod.verts.Length];
        }

        if (normals == null || normals.Length != verts.Length)
        {
            normals = mc.mod.mesh.normals;              // get current normals
        }
        if (penetration == null || penetration.Length != mc.mod.verts.Length)
        {
            penetration = new float[mc.mod.verts.Length];
        }
        mat = Matrix4x4.identity;

        SetAxis(mat);

        return(true);
    }
    public bool recalcBounds = true;                                    // recalc bounds

    // Call this to set the source game object which has the working point cache modifier attached
    public void SetSource(GameObject srcobj)
    {
        if (srcobj)
        {
            if (mesh == null)
            {
                mesh = MegaUtils.GetMesh(gameObject);
            }

            Mesh srcmesh = MegaUtils.GetMesh(srcobj);

            if (srcmesh.vertexCount == mesh.vertexCount)
            {
                obj    = srcobj;
                mod    = (MegaPointCache)srcobj.GetComponent <MegaPointCache>();
                modobj = (MegaModifyObject)srcobj.GetComponent <MegaModifyObject>();
                mesh   = MegaUtils.GetMesh(gameObject);
            }
        }
    }
Example #7
0
    public override bool Prepare(MegaModContext mc)
    {
        if (colmesh == null)
        {
            colmesh = new MegaColliderMesh();
        }

        if (colmesh.obj != hitObject && hitObject != null)
        {
            //Debug.Log("building");

            colmesh = new MegaColliderMesh();

            // This is colldier mesh not this mesh
            colmesh.mesh = MegaUtils.GetMesh(hitObject);
            //Debug.Log("verts " + colmesh.mesh.vertexCount);

            colmesh.verts   = colmesh.mesh.vertices;
            colmesh.tris    = colmesh.mesh.triangles;
            colmesh.normals = colmesh.mesh.normals;
            //colmesh.tree = KDTree.MakeFromPoints(colmesh.verts);
            //colmesh.trilist = new VertTriList(colmesh.mesh);
            colmesh.obj = hitObject;
            //Debug.Log("Col info built");
        }
        //Debug.Log("Done");

        if (hitObject)
        {
            //localPos = transform.worldToLocalMatrix.MultiplyPoint(hitObject.transform.position);
            col = hitObject.collider;
        }

        if (hitObject == null)
        {
            return(false);
        }
        //if ( col == null )
        //return false;

        affected.Clear();
        distances.Clear();

        if (offsets == null || offsets.Length != mc.mod.verts.Length)
        {
            offsets = new Vector3[mc.mod.verts.Length];
        }

        if (normals == null || normals.Length != verts.Length)
        {
            normals = mc.mod.mesh.normals;              // get current normals
        }
        if (penetration == null || penetration.Length != mc.mod.verts.Length)
        {
            penetration = new float[mc.mod.verts.Length];
        }
        mat = Matrix4x4.identity;

        SetAxis(mat);

        return(true);
    }
    // We only need to collision with outside masses so any mass not used 6 times, not if a shell
    // plus we give external links a different stiffness
    // should work from centre of mesh
    // Can easily thread this
    // We have spring builder in my max destruction soft body so use that
    public void VoxelMesh(GameObject obj, float size, bool fill)
    {
        if (obj == null)
        {
            return;
        }

        voxobj = obj;
        Mesh mesh = MegaUtils.GetMesh(voxobj);

        basemesh = mesh;
        int[]     tris  = mesh.triangles;
        Vector3[] verts = mesh.vertices;


        Vector3 meshsize = mesh.bounds.size;

        xs = Mathf.CeilToInt(meshsize.x / size);
        if (xs == 0)
        {
            xs = 1;
        }

        //Debug.Log("ys " + (meshsize.y / size).ToString("0.000"));
        ys = Mathf.CeilToInt(meshsize.y / size);
        if (ys == 0)
        {
            ys = 1;
        }

        zs = Mathf.CeilToInt(meshsize.z / size);
        if (zs == 0)
        {
            zs = 1;
        }

        origin.x = -((float)xs * 0.5f * size);          //mesh.bounds.min + Jitter;
        origin.y = -((float)ys * 0.5f * size);          //mesh.bounds.min + Jitter;
        origin.z = -((float)zs * 0.5f * size);          //mesh.bounds.min + Jitter;

        // So first check all tris against each cell
        // first get bounds of tri

        // is it quicker to do each tri, get bounds and check those
        // or do each cell and check all tris, (can early out on this)

        // alloc array to hold cell data
        cells = new int[xs, ys, zs];

        // Mmmm looks like a lot quicker otherway for 30 verts on a 4x4x4 we loop 4x4x4x30= 1920
        // if we do tri and get bounds then a lot quicker could be as low as 30 or 2x2x2x30 = 240
        Bounds box = new Bounds();

        int gxs, gxe;
        int gys, gye;
        int gzs, gze;

        Vector3 min = Vector3.zero;

        Vector3 half = new Vector3(size * 0.5f, size * 0.5f, size * 0.5f);

        cellsize = new Vector3(size, size, size);

        //Debug.Log("Origin " + origin.ToString("0.000"));
        for (int i = 0; i < tris.Length; i += 3)
        {
            // do bounds on tri
            GetTriBounds(verts, tris, i, origin, out gxs, out gxe, out gys, out gye, out gzs, out gze);

            //Debug.Log("b[" + i + "] " + gxs + " " + gxe + " " + gys + " " + gye + " " + gzs + " " + gze);
            //for ( int z = 0; z < zs; z++ )
            for (int z = gzs; z <= gze; z++)
            {
                min.z = origin.z + (z * size);

                //for ( int y = 0; y < ys; y++ )
                for (int y = gys; y <= gye; y++)
                {
                    min.y = origin.y + (y * size);

                    //for ( int x = 0; x < xs; x++ )
                    for (int x = gxs; x <= gxe; x++)
                    {
                        min.x = origin.x + (x * size);

                        box.SetMinMax(min, min + cellsize);
                        //Debug.Log("box " + box.min.ToString("0.000"));
                        // build box for cell
                        if (AABB_Triangle_Intersection.TriangleBoxOverlap(verts[tris[i]], verts[tris[i + 1]], verts[tris[i + 2]], box))
                        {
                            if (x < xs && y < ys && z < zs)
                            {
                                cells[x, y, z] = 1;
                            }
                            //Debug.Log("hit " + x + " " + y + " " + z);
                        }
                    }
                }
            }
        }

        // We should have a shell now, so now to fill line by line
        // can do for each axis and combine result (bit per axis) any bit means voxel, this will fill holes

        // Fill it, should do for each axis
        // could be a bug here here cant assume pen changes state in next block, so for pen down we get
        // the first block but we need end of contigous block
        if (fill)
        {
            for (int z = 0; z < zs; z++)
            {
                for (int y = 0; y < ys; y++)
                {
                    int pd = 0;
                    while (true)                        //x != -1 )
                    {
                        // get pen down
                        pd = GetXCell(cells, pd, y, z, xs);
                        if (pd == -1)
                        {
                            break;
                        }

                        // get pen up
                        int pu = GetXCell(cells, pd + 1, y, z, xs);

                        if (pu == -1)
                        {
                            break;
                        }

                        for (int x = pd + 1; x < pu; x++)
                        {
                            cells[x, y, z] = 2;
                        }
                        pd = pu + 1;                            // pd is
                    }
                }
            }
        }

        BuildLattice();

        // Build bary coords
        BaryCoord[] barycoords = new BaryCoord[verts.Length];

        for (int i = 0; i < verts.Length; i++)
        {
            Vector3 p = verts[i];

            int x = (int)((p.x - origin.x) / CellSize);
            int y = (int)((p.y - origin.y) / CellSize);
            int z = (int)((p.z - origin.z) / CellSize);

            BaryCoord bc = new BaryCoord();
            bc.p.x = (p.x - origin.x - (float)x * CellSize) / CellSize;
            bc.p.y = (p.y - origin.y - (float)y * CellSize) / CellSize;
            bc.p.z = (p.z - origin.z - (float)z * CellSize) / CellSize;

            for (int c = 0; c < 8; c++)
            {
                bc.m[c] = GetMassIndex(x, y, z, c);
            }
            //bc.m = FindMassIndex(p);
            //Debug.Log("[" + i + "] " + x + " " + y + " " + z + " " + p);
            barycoords[i] = bc;
        }

        // Rebuild verts test
        for (int i = 0; i < barycoords.Length; i++)
        {
            BaryCoord bc = barycoords[i];

            Vector3 bl = Vector3.Lerp(voxmasses[bc.m[0]].p, voxmasses[bc.m[1]].p, bc.p.z);
            Vector3 tl = Vector3.Lerp(voxmasses[bc.m[4]].p, voxmasses[bc.m[5]].p, bc.p.z);

            Vector3 br = Vector3.Lerp(voxmasses[bc.m[3]].p, voxmasses[bc.m[2]].p, bc.p.z);
            Vector3 tr = Vector3.Lerp(voxmasses[bc.m[7]].p, voxmasses[bc.m[6]].p, bc.p.z);

            Vector3 l = Vector3.Lerp(bl, tl, bc.p.y);
            Vector3 r = Vector3.Lerp(br, tr, bc.p.y);

            verts[i] = Vector3.Lerp(l, r, bc.p.x);
        }

        //mesh.vertices = verts;
    }
    // We have spring builder in my max destruction soft body so use that
    public void VoxelMesh(GameObject obj, float size, bool fill)
    {
        if (obj == null)
        {
            return;
        }

        voxobj = obj;
        Mesh mesh = MegaUtils.GetMesh(voxobj);

        basemesh = mesh;
        int[]     tris  = mesh.triangles;
        Vector3[] verts = mesh.vertices;

        origin = mesh.bounds.min;

        Vector3 meshsize = mesh.bounds.size;

        xs = Mathf.CeilToInt(meshsize.x / size);
        if (xs == 0)
        {
            xs = 1;
        }

        ys = Mathf.CeilToInt(meshsize.y / size);
        if (ys == 0)
        {
            ys = 1;
        }

        zs = Mathf.CeilToInt(meshsize.z / size);
        if (zs == 0)
        {
            zs = 1;
        }

        // So first check all tris against each cell
        // first get bounds of tri

        // is it quicker to do each tri, get bounds and check those
        // or do each cell and check all tris, (can early out on this)

        // alloc array to hold cell data
        cells = new int[xs, ys, zs];

        // Mmmm looks like a lot quicker otherway for 30 verts on a 4x4x4 we loop 4x4x4x30= 1920
        // if we do tri and get bounds then a lot quicker could be as low as 30 or 2x2x2x30 = 240
        Bounds box = new Bounds();

        int gxs, gxe;
        int gys, gye;
        int gzs, gze;

        Vector3 min = Vector3.zero;

        Vector3 half = new Vector3(size * 0.5f, size * 0.5f, size * 0.5f);

        cellsize = new Vector3(size, size, size);

        for (int i = 0; i < tris.Length; i += 3)
        {
            // do bounds on tri
            GetTriBounds(verts, tris, i, mesh.bounds, out gxs, out gxe, out gys, out gye, out gzs, out gze);

            for (int z = gzs; z < gze; z++)
            {
                min.z = mesh.bounds.min.z + (z * size);

                for (int y = gys; y < gye; y++)
                {
                    min.y = mesh.bounds.min.y + (y * size);

                    for (int x = gxs; x < gxe; x++)
                    {
                        min.x = mesh.bounds.min.x + (x * size);

                        box.SetMinMax(min, min + cellsize);

                        // build box for cell
                        if (AABB_Triangle_Intersection.TriangleBoxOverlap(verts[tris[i]], verts[tris[i + 1]], verts[tris[i + 2]], box))
                        {
                            cells[x, y, z] = 1;
                        }
                    }
                }
            }
        }

        // We should have a shell now, so now to fill line by line
        // can do for each axis and combine result (bit per axis) any bit means voxel, this will fill holes

        // Fill it, should do for each axis
        // could be a bug here here cant assume pen changes state in next block, so for pen down we get
        // the first block but we need end of contigous block
        if (fill)
        {
            for (int z = 0; z < zs; z++)
            {
                for (int y = 0; y < ys; y++)
                {
                    int pd = 0;
                    while (true)                        //x != -1 )
                    {
                        // get pen down
                        pd = GetXCell(cells, pd, y, z, xs);
                        if (pd == -1)
                        {
                            break;
                        }

                        // get pen up
                        int pu = GetXCell(cells, pd + 1, y, z, xs);

                        if (pu == -1)
                        {
                            break;
                        }

                        for (int x = pd + 1; x < pu; x++)
                        {
                            cells[x, y, z] = 2;
                        }
                        pd = pu + 1;                            // pd is
                    }
                }
            }
        }
    }