public void InitializeParticles() { for (int i = 0; i != mLatticeLocations.Count; ++i) { LatticeLocation ll = mLatticeLocations[i]; for (int j = 0; j != ll.mParticles.Length; ++j) { if (null != ll.mParticles[j]) { continue; } SmParticle sp = GetSharedParticle(ll.mIndex, j); if (null != sp) { ll.mParticles[j] = sp; } else { ll.mParticles[j] = new SmParticle(); sp = ll.mParticles[j]; mParticles.Add(sp); sp.LP = ll; sp.mX0 = GetParticleInitPostion(ll.mIndex, j); sp.Mass = DefaultParticleMass; sp.mX = sp.mX0; sp.mV = Vector3.zero; sp.mF = Vector3.zero; } } } }
public static int CompareSmParticle(SmParticle x, SmParticle y) { if (x == null) { if (y == null) { return(0); } else { return(-1); } } else { if (y == null) { return(1); } else { return(x.CreateTime.CompareTo(y.CreateTime)); } } }
// Update is called once per frame void Update() { for (int i = 0; i != mBodies.Count; ++i) { DeformableModel body = mBodies[i]; body.ShapeMatch(); body.CalculateParticleVelocities(h); body.PerformRegionDamping(); body.ApplyParticleVelocities(h); for (int j = 0; j != body.mParticles.Count; ++j) { SmParticle particle = body.mParticles[j]; particle.mF += vGravity; if (particle.mX.y < 0.0f) { particle.mF.y -= particle.mX.y; //particle.mF = Vector3.zero; particle.mV = Vector3.zero; particle.mX.y = 0.0f; //Debug.Log("Touch[" + j.ToString() + "]"); } } } }
public void CalculateInvariants() { Debug.Log("Calculating invariants..."); for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; particle.PerRegionMass = particle.Mass / particle.mParentRegions.Count; } for (int i = 0; i != mParticles.Count; ++i) { SmParticle p = mParticles[i]; p.mSumData.mM.m00 = p.PerRegionMass; p.mSumData.mV = p.PerRegionMass * p.mX0; } SumParticlesToRegions(); for (int i = 0; i != mRegions.Count; ++i) { SmRegion r = mRegions[i]; r.mM = r.mSumData.mM.m00; r.mEx0 = r.mSumData.mV; r.mC0 = r.mEx0 / r.mM; } Debug.Log(" done."); }
void AddForce() { string[] smBodyName = new string[] { "Penguin", "rubberduck", "Soccerball", "plane_lower" }; foreach (string strName in smBodyName) { GameObject goBody = GameObject.Find(strName); if (null == goBody) { continue; } SmBody sb = goBody.GetComponent <SmBody>(); if (null == sb) { continue; } float velocityMax = 25.0f; float velocityHalf = velocityMax / 2.0f; Vector3 randomVelocity = new Vector3(0, Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf, 0); for (int i = 0; i != sb.mDeformableModel.mParticles.Count; ++i) { SmParticle particle = sb.mDeformableModel.mParticles[i]; //particle.mX.y += 5.0f; particle.mV += (randomVelocity); } } }
public static Summation FindIdenticalSummation(ref List <SmParticle> particles, int myLevel) { for (int m = 0; m != particles.Count; ++m) { LatticeLocation checkLp = particles[m].LP; for (int q = 0; q != checkLp.mSummations[myLevel].Count; ++q) { List <SmParticle> checkParticles = checkLp.mSummations[myLevel][q].mParticles; if (checkParticles.Count == particles.Count) { bool bEqual = true; for (int i = 0; i != checkParticles.Count; ++i) { SmParticle left = checkParticles[i]; SmParticle right = particles[i]; if (left != right) { bEqual = false; break; } } if (bEqual) { return(checkLp.mSummations[myLevel][q]); } } } } return(null); }
/* * public void AddParticle(Point3 index) * { * LatticeLocation l = new LatticeLocation(); * mLatticeLocations.Add(l); * mLattice[index] = l; * l.mIndex = index; * l.Body = this; * l.Region = null; * * for (int xo = -1; xo <= 1; ++xo) * { * for (int yo = -1; yo <= 1; ++yo) * { * for (int zo = -1; zo <= 1; ++zo) * { * Point3 check = new Point3(index.x + xo, index.y + yo, index.z + zo); * if (!(xo == 0 && yo == 0 && zo == 0) && GetLatticeLocation(check) != null) * { * l.mImmediateNeighbors.Add(GetLatticeLocation(check)); * l.mImmediateNeighborsGrid[xo + 1, yo + 1, zo + 1] = GetLatticeLocation(check); * GetLatticeLocation(check).mImmediateNeighbors.Add(l); * GetLatticeLocation(check).mImmediateNeighborsGrid[-xo + 1, -yo + 1, -zo + 1] = l; * } * else * { * l.mImmediateNeighborsGrid[xo + 1, yo + 1, zo + 1] = null; * } * } * } * } * * l.SmParticle = new SmParticle(); * mParticles.Add(l.SmParticle); * l.SmParticle.LP = l; * l.SmParticle.mX0 = Vector3.Scale(new Vector3((float)index.x, (float)index.y, (float)index.z), mSpacing); * l.SmParticle.Mass = DefaultParticleMass; * l.SmParticle.mX = l.SmParticle.mX0; * l.SmParticle.mV = Vector3.zero; * l.SmParticle.mF = Vector3.zero; * } */ public void Complete() { InitializeParticles(); for (int i = 0; i != mLatticeLocations.Count; ++i) { LatticeLocation l = mLatticeLocations[i]; l.IsEdge = (l.mImmediateNeighbors.Count != 26); l.CalculateNeighborhood(); } GenerateSMRegions(); for (int i = 0; i != mRegions.Count; ++i) { SmRegion r = mRegions[i]; for (int j = 0; j != r.mParticles.Count; ++j) { SmParticle p = r.mParticles[j]; p.mParentRegions.Add(r.LP); } } CalculateInvariants(); //InitializeCells(); // Cells help with rendering }
public void ApplyParticleVelocities(float h) { for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; particle.mX = particle.mX + h * particle.mV; } }
void AddForce2() { string[] smBodyName = new string[] { "Penguin", "rubberduck", "Soccerball", "plane_lower" }; foreach (string strName in smBodyName) { GameObject goBody = GameObject.Find(strName); if (null == goBody) { continue; } SmBody sb = goBody.GetComponent <SmBody>(); if (null == sb) { continue; } float velocityMax = 500.0f; float velocityHalf = velocityMax / 2.0f; /* * Vector3 randomVelocity = new Vector3(0, * Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf, * 0); */ Vector3 randomVelocity = new Vector3(Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf, Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf, Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf); /* * for (int i = 0; i != sb.mDeformableModel.mParticles.Count; ++i) * { * SmParticle particle = sb.mDeformableModel.mParticles[i]; * //particle.mX.y += 5.0f; * particle.mV += (randomVelocity); * } */ while (true) { int index = Random.Range(0, sb.mDeformableModel.mLatticeLocations.Count); LatticeLocation ll = sb.mDeformableModel.mLatticeLocations[index]; if (ll.IsEdge) { for (int i = 0; i != ll.mParticles.Length; ++i) { SmParticle particle = ll.mParticles[i]; particle.mF = randomVelocity; } break; } } } }
void OnDrawGizmos() { for (int i = 0; i != mBodies.Count; ++i) { DeformableModel body = mBodies[i]; for (int j = 0; j != body.mParticles.Count; ++j) { SmParticle p = body.mParticles[j]; Gizmos.color = Color.red; Gizmos.DrawSphere(p.mX, 0.1f); } } }
public void CalculateParticleVelocities(float h) { for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; if (particle.mParentRegions.Count == 0) { particle.mV = particle.mV + h * (particle.mF / particle.Mass); particle.mG = particle.mX; } else { particle.mV = particle.mV + Alpha * (particle.mG - particle.mX) / h + h * (particle.mF / particle.Mass); } particle.mF = Vector3.zero; } }
public void FindParticleRange(int dimension, ref int minDim, ref int maxDim) { minDim = int.MaxValue; maxDim = int.MinValue; for (int i = 0; i != mParticles.Count; ++i) { SmParticle p = mParticles[i]; if (p.LP.mIndex[dimension] < minDim) { minDim = p.LP.mIndex[dimension]; } if (p.LP.mIndex[dimension] > maxDim) { maxDim = p.LP.mIndex[dimension]; } } }
public void SumRegionsToParticles() { for (int i = 0; i != mSummations[1].Count; ++i) { Summation plate = mSummations[1][i]; plate.SumFromParents(); } for (int i = 0; i != mSummations[0].Count; ++i) { Summation bar = mSummations[0][i]; bar.SumFromParents(); } for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; particle.SumFromParents(); } }
/* * void OnDrawGizmos() * { * } */ void OnDrawGizmosSelected() { /* * if (null == mMeshFilters) * return; * * Gizmos.color = Color.blue; * Gizmos.DrawWireCube(mBounds.center, mBounds.size); * * Gizmos.color = Color.green; * for (int i = 0; i != mMeshFilters.Length; ++i) * { * MeshFilter mf = mMeshFilters[i]; * Gizmos.DrawWireCube(mf.mesh.bounds.center, mf.mesh.bounds.size); * } * * if (null == mCellInfos) * return; */ /* * int[] dimensions = new int[3]{mCellInfos.GetLength(0), mCellInfos.GetLength(1), mCellInfos.GetLength(2)}; * for (int x = 0; x != dimensions[0]; ++x) * { * for (int y = 0; y != dimensions[1]; ++y) * { * for (int z = 0; z != dimensions[2]; ++z) * { * SmCellInfo info = mCellInfos[x,y,z]; * if (info.mValid) * { * Gizmos.color = new Color(0, 0, 0, 0.1f); * Gizmos.DrawCube(info.mBounds.center, info.mBounds.size); * * Gizmos.color = Color.black; * Gizmos.DrawWireCube(info.mBounds.center, info.mBounds.size); * * Gizmos.color = Color.red; * Gizmos.DrawSphere(info.mBounds.center, 0.05f); * * for (int w = 0; w != mDeformableModel.mParticles.Count; ++w) * { * Gizmos.DrawSphere(mDeformableModel.mParticles[w].mX, 0.03f); * } * * * LatticeLocation ll = mDeformableModel.GetLatticeLocation(new Point3(x,y,z)); * Gizmos.color = Color.gray; * for (int w = 0; w != info.mVertices.Count; ++w) * { * VertexPosition vp = info.mVertices[w]; * Vector3 vPos = * ll.mParticles[0].mX0 * (1.0f - vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + * ll.mParticles[1].mX0 * (vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + * ll.mParticles[3].mX0 * (1.0f - vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + * ll.mParticles[2].mX0 * (1.0f - vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (vp.mOriginPosition.z) + * ll.mParticles[6].mX0 * (vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (vp.mOriginPosition.z) + * ll.mParticles[5].mX0 * (1.0f - vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (vp.mOriginPosition.z) + * ll.mParticles[4].mX0 * (vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + * ll.mParticles[7].mX0 * (vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (vp.mOriginPosition.z); * * Gizmos.DrawSphere(vPos, 0.01f); * } * } * } * } * } */ if (null != mDeformableModel) { for (int j = 0; j != mDeformableModel.mParticles.Count; ++j) { SmParticle p = mDeformableModel.mParticles[j]; Gizmos.color = Color.red; Gizmos.DrawSphere(transform.TransformPoint(p.mX), 0.03f); } for (int j = 0; j != mDeformableModel.mRegions.Count; ++j) { SmRegion r = mDeformableModel.mRegions[j]; Bounds bounds = new Bounds(transform.TransformPoint(r.mParticles[0].mX), Vector3.zero); for (int k = 0; k != r.mParticles.Count; ++k) { bounds.Encapsulate(transform.TransformPoint(r.mParticles[k].mX)); } Gizmos.color = new Color(r.color.r, r.color.g, r.color.b, 0.05f); Gizmos.DrawCube(bounds.center, bounds.size); Gizmos.color = r.color; Gizmos.DrawWireCube(bounds.center, bounds.size); } } }
public List <Summation> GenerateChildSums(int childLevel) { int splitDimension = childLevel; FindParticleRange(splitDimension, ref mMinDim, ref mMaxDim); List <Summation> newSums = new List <Summation>(); Summation[] childArray = new Summation[mMaxDim - mMinDim + 1]; for (int i = 0; i != mMaxDim - mMinDim + 1; ++i) { childArray[i] = new Summation(); } for (int i = 0; i != mParticles.Count; ++i) { SmParticle p = mParticles[i]; childArray[p.LP.mIndex[splitDimension] - mMinDim].mParticles.Add(p); } for (int i = mMinDim; i <= mMaxDim; ++i) { Summation child = childArray[i - mMinDim]; if (child.mParticles.Count == 0) { child = null; childArray[i - mMinDim] = null; } else { child.mParticles.Sort(SmParticle.CompareSmParticle); child.LP = child.mParticles[0].LP; Summation identical = FindIdenticalSummation(ref child.mParticles, childLevel); if (null != identical) { child = null; childArray[i - mMinDim] = null; mChildren.Add(identical); identical.mParents.Add(this); } else { newSums.Add(child); mChildren.Add(child); child.mParents.Add(this); child.LP.mSummations[childLevel].Add(child); LP.Body.mSummations[childLevel].Add(child); if (childLevel > 0) { child.GenerateChildSums(childLevel - 1); } else { for (int m = 0; m != child.mParticles.Count; ++m) { SmParticle p = child.mParticles[m]; child.mChildren.Add(p); p.mParents.Add(child); } } } } } System.Array.Clear(childArray, 0, childArray.Length); System.Array.Resize(ref childArray, 0); return(newSums); }
void AddBody() { GameObject goPenguin = GameObject.Find("Penguin"); if (null == goPenguin) { return; } SmBody smBody = goPenguin.GetComponent <SmBody>(); if (null == smBody) { return; } DeformableModel body = new DeformableModel(new Vector3(smBody.Spacing, smBody.Spacing, smBody.Spacing)); //body.W = 1; //body.Alpha = Random.Range(0.1f, 1.0f); //body.RegionDamping = Random.Range(0.1f, 1.0f); body.W = 1; body.Alpha = 0.75f; body.RegionDamping = 0.25f; mBodies.Add(body); //int width = Random.Range(0, 3) + 2; //int height = Random.Range(0, 20) + 2; //int depth = Random.Range(0, 3) + 2; int width = smBody.mCellInfos.GetLength(0); int height = smBody.mCellInfos.GetLength(1); int depth = smBody.mCellInfos.GetLength(2); for (int x = 0; x != width; ++x) { for (int y = 0; y != height; ++y) { for (int z = 0; z != depth; ++z) { SmBody.SmCellInfo info = smBody.mCellInfos[x, y, z]; if (info.mValid) { //body.AddParticle(new Point3(x, y, z)); body.AddCell(new Point3(x, y, z)); } } } } body.Complete(); float velocityMax = 25.0f; float velocityHalf = velocityMax / 2.0f; Vector3 randomVelocity = new Vector3(Random.Range(0.0f, 1.0f) * velocityMax - velocityHalf, Random.Range(0.5f, 1.0f) * velocityMax - velocityHalf, Random.Range(0.0f, 1.0f) * velocityMax - velocityHalf); //Vector3 randomVelocity = new Vector3(0.5f * velocityMax - velocityHalf, // 0.5f * velocityMax - velocityHalf, // 0.5f * velocityMax - velocityHalf); //Vector3 randomVelocity = new Vector3(9.0f, 2.8f, -6.8f); for (int i = 0; i != body.mParticles.Count; ++i) { SmParticle particle = body.mParticles[i]; particle.mX.y += 5.0f; particle.mV += (randomVelocity); } Debug.LogWarning("W[" + body.W.ToString() + "], Width[" + width.ToString() + "], Height[" + height.ToString() + "], Depth[" + depth.ToString() + "], Velocity[" + randomVelocity.ToString() + "]"); }
public void PerformRegionDamping() { if (RegionDamping == 0.0f) { return; } for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; particle.mSumData.mV = particle.PerRegionMass * particle.mV; particle.mSumData.mM.SetColumn(0, Vector3.Cross(particle.mX, particle.mSumData.mV)); Vector3 x = particle.mX; particle.mSumData.mM.m21 = particle.PerRegionMass * (x.z * x.z + x.y * x.y); particle.mSumData.mM.m01 = particle.PerRegionMass * (-x.x * x.y); particle.mSumData.mM.m02 = particle.PerRegionMass * (-x.x * x.z); particle.mSumData.mM.m11 = particle.PerRegionMass * (x.z * x.z + x.x * x.x); particle.mSumData.mM.m12 = particle.PerRegionMass * (-x.z * x.y); particle.mSumData.mM.m22 = particle.PerRegionMass * (x.y * x.y + x.x * x.x); } SumParticlesToRegions(); for (int i = 0; i != mRegions.Count; ++i) { SmRegion region = mRegions[i]; Vector3 v = Vector3.zero; Vector3 L = Vector3.zero; Matrix3x3 I = Matrix3x3.zero; Matrix3x3 FmixixiT = new Matrix3x3( region.mSumData.mM.m21, region.mSumData.mM.m01, region.mSumData.mM.m02, region.mSumData.mM.m01, region.mSumData.mM.m11, region.mSumData.mM.m12, region.mSumData.mM.m02, region.mSumData.mM.m12, region.mSumData.mM.m22); v = (1.0f / region.mM) * region.mSumData.mV; L = region.mSumData.mM.GetColumn(0) - Vector3.Cross(region.mC, region.mSumData.mV); I = FmixixiT - region.mM * MrMatrix(ref region.mC); Vector3 w = I.inverse * L; region.mSumData.mV = v; region.mSumData.mM.SetColumn(0, w); region.mSumData.mM.SetColumn(1, Vector3.Cross(w, region.mC)); } SumRegionsToParticles(); for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; if (particle.mParentRegions.Count > 0) { Vector3 Fv = particle.mSumData.mV; Vector3 Fw = particle.mSumData.mM.GetColumn(0); Vector3 Fwc = particle.mSumData.mM.GetColumn(1); Vector3 dv = (1.0f / particle.mParentRegions.Count) * (Fv + Vector3.Cross(Fw, particle.mX) - Fwc - (float)particle.mParentRegions.Count * particle.mV); particle.mV = particle.mV + RegionDamping * dv; } } }
// Simulation public void ShapeMatch() { if (IsDirty) { CalculateInvariants(); IsDirty = false; } for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; particle.mSumData.mV = particle.PerRegionMass * particle.mX; particle.mSumData.mM = Matrix3x3.MultiplyWithTranspose(particle.PerRegionMass * particle.mX, particle.mX0); } SumParticlesToRegions(); for (int i = 0; i != mRegions.Count; ++i) { SmRegion r = mRegions[i]; Vector3 Fmixi = r.mSumData.mV; Matrix3x3 Fmixi0T = r.mSumData.mM; r.mC = (1 / r.mM) * Fmixi; //9 r.mA = Fmixi0T - Matrix3x3.MultiplyWithTranspose(r.mM * r.mC, r.mC0); Matrix3x3 S = r.mA.transpose * r.mA; S = r.mEigenVectors.transpose * S * r.mEigenVectors; float[] eigenValues = new float[3]; Jacobi.jacobi(3, ref S, ref eigenValues, ref r.mEigenVectors); for (int j = 0; j != 3; ++j) { if (eigenValues[j] <= 0.0f) { eigenValues[j] = 0.05f; } eigenValues[j] = 1.0f / Mathf.Sqrt(eigenValues[j]); } Matrix3x3 DPrime = new Matrix3x3(eigenValues[0], 0, 0, 0, eigenValues[1], 0, 0, 0, eigenValues[2]); S = r.mEigenVectors * DPrime * r.mEigenVectors.transpose; r.mR = r.mA * S; if (r.mR.determinant < 0) { r.mR *= (-1.0f); } r.mT = r.mC - r.mR * r.mC0; r.mSumData.mM = r.mR; r.mSumData.mV = r.mT; } SumRegionsToParticles(); for (int i = 0; i != mParticles.Count; ++i) { SmParticle particle = mParticles[i]; float invNumParentRegions = 1.0f / particle.mParentRegions.Count; particle.mG = (invNumParentRegions * particle.mSumData.mM) * particle.mX0 + invNumParentRegions * particle.mSumData.mV; particle.mR = invNumParentRegions * particle.mSumData.mM; } }
// Update is called once per frame void Update() { if (null != mDeformableModel) { mDeformableModel.ShapeMatch(); mDeformableModel.CalculateParticleVelocities(h); mDeformableModel.PerformRegionDamping(); mDeformableModel.ApplyParticleVelocities(h); for (int j = 0; j != mDeformableModel.mParticles.Count; ++j) { SmParticle particle = mDeformableModel.mParticles[j]; particle.mF += vGravity; if (particle.mX.y < 0.0f) { particle.mF.y -= particle.mX.y; particle.mV = Vector3.zero; particle.mX.y = 0.0f; } } } //deform mesh for (int x = 0; x != mCellInfos.GetLength(0); ++x) { for (int y = 0; y != mCellInfos.GetLength(1); ++y) { for (int z = 0; z != mCellInfos.GetLength(2); ++z) { SmCellInfo info = mCellInfos[x, y, z]; if (info.mValid) { LatticeLocation ll = mDeformableModel.GetLatticeLocation(new Point3(x, y, z)); if (null == ll) { continue; } for (int w = 0; w != info.mVertices.Count; ++w) { VertexPosition vp = info.mVertices[w]; mMeshVertices[vp.mMeshIndex][vp.mVertexIndex] = ll.mParticles[0].mX * (1.0f - vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + ll.mParticles[1].mX * (vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + ll.mParticles[3].mX * (1.0f - vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (vp.mOriginPosition.z) + ll.mParticles[2].mX * (1.0f - vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + ll.mParticles[6].mX * (vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (1.0f - vp.mOriginPosition.z) + ll.mParticles[5].mX * (1.0f - vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (vp.mOriginPosition.z) + ll.mParticles[4].mX * (vp.mOriginPosition.x) * (1.0f - vp.mOriginPosition.y) * (vp.mOriginPosition.z) + ll.mParticles[7].mX * (vp.mOriginPosition.x) * (vp.mOriginPosition.y) * (vp.mOriginPosition.z); } } } } } Vector3 vLocal = Vector3.zero; Vector3 vOrigin = Vector3.zero; for (int i = 0; i != mMeshFilters.Length; ++i) { MeshFilter mf = mMeshFilters[i]; for (int j = 0; j != mMeshVertices[i].Length; ++j) { vLocal = mMeshVertices[i][j]; vOrigin = mMeshTransforms[i].InverseTransformPoint(transform.TransformPoint(vLocal)); mMeshVertices[i][j] = vOrigin; } mf.mesh.vertices = mMeshVertices[i]; mf.mesh.RecalculateNormals(); mf.mesh.RecalculateBounds(); } }