void FinalizeConstruction() { if (bvs.Count == 1) { // this node is leaf box = bvs[0]; isLeaf = true; return; } // find bounding box for bvs box = new kDOP24(); foreach (kDOP24 bv in bvs) { box.Expand(bv); } double dX, dY, dZ; box.Dimensions(out dX, out dY, out dZ); // arrays where left and right portions will be stored List <kDOP24> left = new List <kDOP24>(bvs.Count); List <kDOP24> right = new List <kDOP24>(bvs.Count); // identify splitting axis and split if (dX >= dY && dX >= dZ) { double center = box.centerX; foreach (kDOP24 bv in bvs) { if (bv.centerX < center) { left.Add(bv); } else { right.Add(bv); } } // make sure that there is at least one element on each side if (left.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in right) { if (min1 >= bv.centerX) { min1 = bv.centerX; selected = bv; } } left.Add(selected); right.Remove(selected); } else if (right.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in left) { if (min1 >= bv.centerX) { min1 = bv.centerX; selected = bv; } } right.Add(selected); left.Remove(selected); } } else if (dY >= dX && dY >= dZ) { double center = box.centerY; foreach (kDOP24 bv in bvs) { if (bv.centerY < center) { left.Add(bv); } else { right.Add(bv); } } if (left.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in right) { if (min1 >= bv.centerY) { min1 = bv.centerY; selected = bv; } } left.Add(selected); right.Remove(selected); } else if (right.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in left) { if (min1 >= bv.centerY) { min1 = bv.centerY; selected = bv; } } right.Add(selected); left.Remove(selected); } } else { double center = box.centerZ; foreach (kDOP24 bv in bvs) { if (bv.centerZ < center) { left.Add(bv); } else { right.Add(bv); } } if (left.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in right) { if (min1 >= bv.centerZ) { min1 = bv.centerZ; selected = bv; } } left.Add(selected); right.Remove(selected); } else if (right.Count == 0) { kDOP24 selected = null; double min1 = double.MaxValue; foreach (kDOP24 bv in left) { if (min1 >= bv.centerZ) { min1 = bv.centerZ; selected = bv; } } right.Add(selected); left.Remove(selected); } } left.TrimExcess(); right.TrimExcess(); child1 = new BVHN(this, left, level + 1); child2 = new BVHN(this, right, level + 1); }
public void PrepareToCompute() { // this is called once before simulation starts mc.Prepare(); if (cf == null) { mc.Reset(); // initialize current frame cf = new FrameInfo(); cf.TimeScaleFactor = 16; allFrames.Clear(); allFrames.Add(cf); cf.nCZ_Initial = mc.nonFailedCZs.Length; SaveSimulationInitialState(); SaveStep(); gf.prms = prms; gf.SetConstants(); } // identify and mark anchored nodes foreach (Mesh deformableMesh in mc.deformables) { foreach (SurfaceFragment sf in deformableMesh.surfaceFragments) { if (sf.role == SurfaceFragment.SurfaceRole.Anchored) { foreach (int idx in sf.faces) { Face f = deformableMesh.faces[idx]; foreach (Node nd in f.vrts) { nd.anchored = true; nd.altId = -1; } } } } } mc.activeNodes = Array.FindAll(mc.allNodes, nd => { return(nd.anchored == false); }); for (int i = 0; i < mc.activeNodes.Length; i++) { mc.activeNodes[i].altId = i; } if (allFrames[allFrames.Count - 1] != cf) { // trim frame list int from = cf.StepNumber + 1; int qty = allFrames.Count - cf.StepNumber - 1; allFrames.RemoveRange(cf.StepNumber + 1, allFrames.Count - cf.StepNumber - 1); } // find surface elements in all meshes, create leaf KDOP list bvh.b24.Clear(); bvh.prms = prms; bvh.ForceReconstruct(); foreach (Mesh mg in mc.mgs) { mg.IdentifySurfaceElements(); mg.ConnectFaces(); foreach (Element elem in mg.surfaceElements) { kDOP24 k = new kDOP24(); k.elem = elem; bvh.b24.Add(k); elem.FindAdjFaces(); } } mc.PrepareSurfaceElements(); mc.UpdateStaticStructureData(linearSystem.csrd); gf.linearSystem = linearSystem; gf.prms = prms; gf.mc = mc; gf.ctx.SetCurrent(); gf.cf = cf; gf.TransferStaticDataToDevice(); isReady = true; }