internal void AddPrimToScene(BulletDotNETPrim pPrim) { lock (m_prims) { if (!m_prims.Contains(pPrim)) { try { m_prims.Add(pPrim); m_primsLocalID.Add(pPrim.m_localID, pPrim); } catch { // noop if it's already there m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID"); } m_world.addRigidBody(pPrim.Body); // m_log.Debug("[PHYSICS] added prim to scene"); } } }
internal void addActivePrim(BulletDotNETPrim pPrim) { lock (m_activePrims) { if (!m_activePrims.Contains(pPrim)) { m_activePrims.Add(pPrim); } } }
public void remActivePrim(BulletDotNETPrim pDeactivatePrim) { lock (m_activePrims) { m_activePrims.Remove(pDeactivatePrim); } }
private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) { Vector3 pos = position; //pos.X = position.X; //pos.Y = position.Y; //pos.Z = position.Z; Vector3 siz = Vector3.Zero; siz.X = size.X; siz.Y = size.Y; siz.Z = size.Z; Quaternion rot = rotation; BulletDotNETPrim newPrim; lock (BulletLock) { newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical); //lock (m_prims) // m_prims.Add(newPrim); } return newPrim; }
internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body) { lock (m_prims) { if (m_prims.Contains(prm)) { m_world.removeRigidBody(body); } remActivePrim(prm); m_primsLocalID.Remove(prm.m_localID); m_prims.Remove(prm); } }
internal void ParentPrim(BulletDotNETPrim prm) { if (prm == null) return; lock (childrenPrim) { if (!childrenPrim.Contains(prm)) { childrenPrim.Add(prm); } } }
internal void AddPrimToScene(BulletDotNETPrim pPrim) { lock (m_prims) { if (!m_prims.Contains(pPrim)) { m_prims.Add(pPrim); m_world.addRigidBody(pPrim.Body); m_log.Debug("ADDED"); } } }
private void ChildDelink(BulletDotNETPrim pPrim) { // Okay, we have a delinked child.. need to rebuild the body. lock (childrenPrim) { foreach (BulletDotNETPrim prm in childrenPrim) { prm.childPrim = true; prm.disableBody(); } } disableBody(); lock (childrenPrim) { childrenPrim.Remove(pPrim); } if (Body != null && Body.Handle != IntPtr.Zero) { _parent_scene.remActivePrim(this); } lock (childrenPrim) { foreach (BulletDotNETPrim prm in childrenPrim) { ParentPrim(prm); } } }
private float CalculateMass() { float volume = 0; // No material is passed to the physics engines yet.. soo.. // we're using the m_density constant in the class definition float returnMass = 0; switch (_pbs.ProfileShape) { case ProfileShape.Square: // Profile Volume volume = _size.X * _size.Y * _size.Z; // If the user has 'hollowed out' // ProfileHollow is one of those 0 to 50000 values :P // we like percentages better.. so turning into a percentage if (((float)_pbs.ProfileHollow / 50000f) > 0.0) { float hollowAmount = (float)_pbs.ProfileHollow / 50000f; // calculate the hollow volume by it's shape compared to the prim shape float hollowVolume = 0; switch (_pbs.HollowShape) { case HollowShape.Square: case HollowShape.Same: // Cube Hollow volume calculation float hollowsizex = _size.X * hollowAmount; float hollowsizey = _size.Y * hollowAmount; float hollowsizez = _size.Z * hollowAmount; hollowVolume = hollowsizex * hollowsizey * hollowsizez; break; case HollowShape.Circle: // Hollow shape is a perfect cyllinder in respect to the cube's scale // Cyllinder hollow volume calculation float hRadius = _size.X / 2; float hLength = _size.Z; // pi * r2 * h hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); break; case HollowShape.Triangle: // Equilateral Triangular Prism volume hollow calculation // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y float aLength = _size.Y; // 1/2 abh hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); break; default: hollowVolume = 0; break; } volume = volume - hollowVolume; } break; case ProfileShape.Circle: if (_pbs.PathCurve == (byte)Extrusion.Straight) { // Cylinder float volume1 = (float)(Math.PI * Math.Pow(_size.X / 2, 2) * _size.Z); float volume2 = (float)(Math.PI * Math.Pow(_size.Y / 2, 2) * _size.Z); // Approximating the cylinder's irregularity. if (volume1 > volume2) { volume = (float)volume1 - (volume1 - volume2); } else if (volume2 > volume1) { volume = (float)volume2 - (volume2 - volume1); } else { // Regular cylinder volume = volume1; } } else { // We don't know what the shape is yet, so use default volume = _size.X * _size.Y * _size.Z; } // If the user has 'hollowed out' // ProfileHollow is one of those 0 to 50000 values :P // we like percentages better.. so turning into a percentage if (((float)_pbs.ProfileHollow / 50000f) > 0.0) { float hollowAmount = (float)_pbs.ProfileHollow / 50000f; // calculate the hollow volume by it's shape compared to the prim shape float hollowVolume = 0; switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Circle: // Hollow shape is a perfect cyllinder in respect to the cube's scale // Cyllinder hollow volume calculation float hRadius = _size.X / 2; float hLength = _size.Z; // pi * r2 * h hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); break; case HollowShape.Square: // Cube Hollow volume calculation float hollowsizex = _size.X * hollowAmount; float hollowsizey = _size.Y * hollowAmount; float hollowsizez = _size.Z * hollowAmount; hollowVolume = hollowsizex * hollowsizey * hollowsizez; break; case HollowShape.Triangle: // Equilateral Triangular Prism volume hollow calculation // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y float aLength = _size.Y; // 1/2 abh hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); break; default: hollowVolume = 0; break; } volume = volume - hollowVolume; } break; case ProfileShape.HalfCircle: if (_pbs.PathCurve == (byte)Extrusion.Curve1) { if (_size.X == _size.Y && _size.Z == _size.X) { // regular sphere // v = 4/3 * pi * r^3 float sradius3 = (float)Math.Pow((_size.X / 2), 3); volume = (float)((4 / 3f) * Math.PI * sradius3); } else { // we treat this as a box currently volume = _size.X * _size.Y * _size.Z; } } else { // We don't know what the shape is yet, so use default volume = _size.X * _size.Y * _size.Z; } break; case ProfileShape.EquilateralTriangle: /* v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h // seed mesh Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); Vertex PM = new Vertex(+0.5f, 0f, 0.0f); Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); */ float xA = -0.25f * _size.X; float yA = -0.45f * _size.Y; float xB = 0.5f * _size.X; float yB = 0; float xC = -0.25f * _size.X; float yC = 0.45f * _size.Y; volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); // If the user has 'hollowed out' // ProfileHollow is one of those 0 to 50000 values :P // we like percentages better.. so turning into a percentage float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); if (((float)fhollowFactor / 50000f) > 0.0) { float hollowAmount = (float)fhollowFactor / 50000f; // calculate the hollow volume by it's shape compared to the prim shape float hollowVolume = 0; switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: // Equilateral Triangular Prism volume hollow calculation // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y float aLength = _size.Y; // 1/2 abh hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); break; case HollowShape.Square: // Cube Hollow volume calculation float hollowsizex = _size.X * hollowAmount; float hollowsizey = _size.Y * hollowAmount; float hollowsizez = _size.Z * hollowAmount; hollowVolume = hollowsizex * hollowsizey * hollowsizez; break; case HollowShape.Circle: // Hollow shape is a perfect cyllinder in respect to the cube's scale // Cyllinder hollow volume calculation float hRadius = _size.X / 2; float hLength = _size.Z; // pi * r2 * h hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength) / 2) * hollowAmount); break; default: hollowVolume = 0; break; } volume = volume - hollowVolume; } break; default: // we don't have all of the volume formulas yet so // use the common volume formula for all volume = _size.X * _size.Y * _size.Z; break; } // Calculate Path cut effect on volume // Not exact, in the triangle hollow example // They should never be zero or less then zero.. // we'll ignore it if it's less then zero // ProfileEnd and ProfileBegin are values // from 0 to 50000 // Turning them back into percentages so that I can cut that percentage off the volume float PathCutEndAmount = _pbs.ProfileEnd; float PathCutStartAmount = _pbs.ProfileBegin; if (((PathCutStartAmount + PathCutEndAmount) / 50000f) > 0.0f) { float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount) / 50000f); // Check the return amount for sanity if (pathCutAmount >= 0.99f) pathCutAmount = 0.99f; volume = volume - (volume * pathCutAmount); } UInt16 taperX = _pbs.PathScaleX; UInt16 taperY = _pbs.PathScaleY; float taperFactorX = 0; float taperFactorY = 0; // Mass = density * volume if (taperX != 100) { if (taperX > 100) { taperFactorX = 1.0f - ((float)taperX / 200); //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); } else { taperFactorX = 1.0f - ((100 - (float)taperX) / 100); //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); } volume = (float)volume * ((taperFactorX / 3f) + 0.001f); } if (taperY != 100) { if (taperY > 100) { taperFactorY = 1.0f - ((float)taperY / 200); //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); } else { taperFactorY = 1.0f - ((100 - (float)taperY) / 100); //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); } volume = (float)volume * ((taperFactorY / 3f) + 0.001f); } returnMass = m_density * volume; if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. // Recursively calculate mass bool HasChildPrim = false; lock (childrenPrim) { if (childrenPrim.Count > 0) { HasChildPrim = true; } } if (HasChildPrim) { BulletDotNETPrim[] childPrimArr = new BulletDotNETPrim[0]; lock (childrenPrim) childPrimArr = childrenPrim.ToArray(); for (int i = 0; i < childPrimArr.Length; i++) { if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove) returnMass += childPrimArr[i].CalculateMass(); // failsafe, this shouldn't happen but with OpenSim, you never know :) if (i > 256) break; } } return returnMass; }
private void ChildSetGeom(BulletDotNETPrim bulletDotNETPrim) { // TODO: throw new NotImplementedException(); }
internal void Enable(btRigidBody pBody, BulletDotNETPrim prim) { m_prim = prim; m_body = pBody; }
internal void ParentPrim(BulletDotNETPrim prm) { if (prm == null) return; lock (childrenPrim) { if (!childrenPrim.Contains(prm)) { childrenPrim.Add(prm); if (m_vehicle.Type != Vehicle.TYPE_NONE) { m_vehicle.Enable(prm.Body, prm); } } } }