void SetMesh() { if (basemesh) { // Rebuild verts test for (int i = 0; i < barycoords.Length; i++) { BaryCoord bc = barycoords[i]; Vector3 bl = Vector3.Lerp(softbody.masses[bc.m[0]].pos, softbody.masses[bc.m[1]].pos, bc.p.z); Vector3 tl = Vector3.Lerp(softbody.masses[bc.m[4]].pos, softbody.masses[bc.m[5]].pos, bc.p.z); Vector3 br = Vector3.Lerp(softbody.masses[bc.m[3]].pos, softbody.masses[bc.m[2]].pos, bc.p.z); Vector3 tr = Vector3.Lerp(softbody.masses[bc.m[7]].pos, softbody.masses[bc.m[6]].pos, 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); } basemesh.vertices = verts; basemesh.RecalculateNormals(); } }
override public void TurnDynamics(bool bON) { if (bON) { _nposCtrl.TurnON(); } else { _nposCtrl.TurnOFF(); } foreach (var an in _Anims) { if (bON) { an.enabled = true; an.StartPlayback(); } else { an.enabled = false; an.StopPlayback(); } } foreach (var crctrl in _crCtrls) { crctrl.enabled = bON; } BaryCoord bary = GetComponent <BaryCoord> (); bary.enabled = bON; }
// 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 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; }