12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using Axiom.Math;
- using Ode.NET;
- using OpenSim.Framework;
- using OpenSim.Region.Physics.Manager;
- namespace OpenSim.Region.Physics.OdePlugin
- {
- public class OdePrim : PhysicsActor
- {
- private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- public PhysicsVector _position;
- private PhysicsVector _velocity;
- private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
- private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
- private PhysicsVector m_rotationalVelocity;
- private PhysicsVector _size;
- private PhysicsVector _acceleration;
- private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
- private Quaternion _orientation;
- private PhysicsVector m_taintposition;
- private PhysicsVector m_taintsize;
- private PhysicsVector m_taintVelocity = PhysicsVector.Zero;
- private Quaternion m_taintrot;
- private PhysicsVector m_PIDTarget = new PhysicsVector(0, 0, 0);
- private float m_PIDTau = 0f;
- private bool m_usePID = false;
- private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
- | CollisionCategories.Space
- | CollisionCategories.Body
- | CollisionCategories.Character
- );
- private bool m_taintshape = false;
- private bool m_taintPhysics = false;
- private bool m_collidesLand = true;
- private bool m_collidesWater = false;
- public bool m_returnCollisions = false;
- // Default we're a Geometry
- private CollisionCategories m_collisionCategories = (CollisionCategories.Geom );
- // Default, Collide with Other Geometries, spaces and Bodies
- private CollisionCategories m_collisionFlags = m_default_collisionFlags;
- public bool m_taintremove = false;
- public bool m_taintdisable = false;
- public bool m_disabled = false;
- public bool m_taintadd = false;
- public bool m_taintselected = false;
- public bool m_taintCollidesWater = false;
- public uint m_localID = 0;
- public GCHandle gc;
- private CollisionLocker ode;
- private bool m_taintforce = false;
- private List<PhysicsVector> m_forcelist = new List<PhysicsVector>();
- private IMesh _mesh;
- private PrimitiveBaseShape _pbs;
- private OdeScene _parent_scene;
- public IntPtr m_targetSpace = (IntPtr) 0;
- public IntPtr prim_geom;
- public IntPtr prev_geom;
- public IntPtr _triMeshData;
- private IntPtr _linkJointGroup = (IntPtr)0;
- private PhysicsActor _parent = null;
- private PhysicsActor m_taintparent = null;
-
- private bool iscolliding = false;
- private bool m_isphysical = false;
- private bool m_isSelected = false;
- private bool m_throttleUpdates = false;
- private int throttleCounter = 0;
- public int m_interpenetrationcount = 0;
- public int m_collisionscore = 0;
- public int m_roundsUnderMotionThreshold = 0;
- private int m_crossingfailures = 0;
- public float m_buoyancy = 0f;
- public bool outofBounds = false;
- private float m_density = 10.000006836f; // Aluminum g/cm3;
- public bool _zeroFlag = false;
- private bool m_lastUpdateSent = false;
- public IntPtr Body = (IntPtr) 0;
- private String m_primName;
- private PhysicsVector _target_velocity;
- public d.Mass pMass;
- private IntPtr m_linkJoint = (IntPtr)0;
- public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
- Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
- {
- _target_velocity = new PhysicsVector(0, 0, 0);
- gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
- ode = dode;
- _velocity = new PhysicsVector();
- _position = pos;
- m_taintposition = pos;
- if (_position.X > 257)
- {
- _position.X = 257;
- }
- if (_position.X < 0)
- {
- _position.X = 0;
- }
- if (_position.Y > 257)
- {
- _position.Y = 257;
- }
- if (_position.Y < 0)
- {
- _position.Y = 0;
- }
- prim_geom = (IntPtr)0;
- prev_geom = (IntPtr)0;
- _size = size;
- m_taintsize = _size;
- _acceleration = new PhysicsVector();
- m_rotationalVelocity = PhysicsVector.Zero;
- _orientation = rotation;
- m_taintrot = _orientation;
- _mesh = mesh;
- _pbs = pbs;
- _parent_scene = parent_scene;
- m_targetSpace = (IntPtr)0;
- if (pos.Z < 0)
- m_isphysical = false;
- else
- {
- m_isphysical = pisPhysical;
- // If we're physical, we need to be in the master space for now.
- // linksets *should* be in a space together.. but are not currently
- if (m_isphysical)
- m_targetSpace = _parent_scene.space;
- }
- m_primName = primName;
- m_taintadd = true;
- _parent_scene.AddPhysicsActorTaint(this);
- // don't do .add() here; old geoms get recycled with the same hash
-
- }
- /// <summary>
- /// Nasty, however without this you get
- /// 'invalid operation for locked space' when things are really loaded down
- /// </summary>
- /// <param name="space"></param>
-
- public override int PhysicsActorType
- {
- get { return (int) ActorTypes.Prim; }
- set { return; }
- }
- public override bool SetAlwaysRun
- {
- get { return false; }
- set { return; }
- }
- public override uint LocalID
- {
- set {
- //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
- m_localID = value; }
- }
- public override bool Grabbed
- {
- set { return; }
- }
- public override bool Selected
- {
- set {
- // This only makes the object not collidable if the object
- // is physical or the object is modified somehow *IN THE FUTURE*
- // without this, if an avatar selects prim, they can walk right
- // through it while it's selected
- if ((m_isphysical && !_zeroFlag) || !value)
- {
- m_taintselected = value;
- _parent_scene.AddPhysicsActorTaint(this);
- }
- else
- {
- m_taintselected = value;
- m_isSelected = value;
- }
- }
- }
- public void SetGeom(IntPtr geom)
- {
- prev_geom = prim_geom;
- prim_geom = geom;
- if (prim_geom != (IntPtr)0)
- {
- d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- }
- //m_log.Warn("Setting Geom to: " + prim_geom);
-
- }
- public void enableBodySoft()
- {
- if (m_isphysical)
- if (Body != (IntPtr)0)
- d.BodyEnable(Body);
- m_disabled = false;
- }
- public void disableBodySoft()
- {
- m_disabled = true;
-
- if (m_isphysical)
- if (Body != (IntPtr)0)
- d.BodyDisable(Body);
- }
- public void enableBody()
- {
- // Sets the geom to a body
- Body = d.BodyCreate(_parent_scene.world);
- setMass();
- d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.BodySetQuaternion(Body, ref myrot);
- d.GeomSetBody(prim_geom, Body);
- m_collisionCategories |= CollisionCategories.Body;
- m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
- d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- d.BodySetAutoDisableFlag(Body, true);
- d.BodySetAutoDisableSteps(Body, 20);
-
- m_interpenetrationcount = 0;
- m_collisionscore = 0;
- m_disabled = false;
- _parent_scene.addActivePrim(this);
- }
- #region Mass Calculation
- 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.Z && _size.Z == _size.X)
- {
- // regular sphere
- // v = 4/3 * pi * r^3
- float sradius3 = (float)Math.Pow((_size.X / 2), 3);
- volume = (float)((4 / 3) * 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;
- return returnMass;
- }
- #endregion
- public void setMass()
- {
- if (Body != (IntPtr) 0)
- {
- float newmass = CalculateMass();
- //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
- if (newmass <= 0) newmass = 0.0001f;
- d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
- d.BodySetMass(Body, ref pMass);
- }
- }
- public void disableBody()
- {
- //this kills the body so things like 'mesh' can re-create it.
- lock (this)
- {
- if (Body != (IntPtr)0)
- {
- m_collisionCategories &= ~CollisionCategories.Body;
- m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
- if (prim_geom != (IntPtr)0)
- {
- d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- }
- _parent_scene.remActivePrim(this);
- d.BodyDestroy(Body);
- Body = (IntPtr)0;
- }
- }
- m_disabled = true;
- m_collisionscore = 0;
- }
- public void setMesh(OdeScene parent_scene, IMesh mesh)
- {
- // This sleeper is there to moderate how long it takes between
- // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
-
- System.Threading.Thread.Sleep(10);
-
- //Kill Body so that mesh can re-make the geom
- if (IsPhysical && Body != (IntPtr) 0)
- {
- disableBody();
- }
- float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
- int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
- int VertexCount = vertexList.GetLength(0)/3;
- int IndexCount = indexList.GetLength(0);
- _triMeshData = d.GeomTriMeshDataCreate();
- d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
- 3*sizeof (int));
- d.GeomTriMeshDataPreprocess(_triMeshData);
-
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
-
- try
- {
- if (prim_geom == (IntPtr)0)
- {
- SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
- }
- }
- catch (System.AccessViolationException)
- {
-
- m_log.Error("[PHYSICS]: MESH LOCKED");
- return;
- }
- if (IsPhysical && Body == (IntPtr) 0)
- {
- // Recreate the body
- m_interpenetrationcount = 0;
- m_collisionscore = 0;
-
- enableBody();
- }
- }
- public void ProcessTaints(float timestep)
- {
-
- if (m_taintadd)
- {
- changeadd(timestep);
- }
- if (prim_geom != (IntPtr)0)
- {
- if (m_taintposition != _position)
- changemove(timestep);
- if (m_taintrot != _orientation)
- rotate(timestep);
- //
- if (m_taintPhysics != m_isphysical)
- changePhysicsStatus(timestep);
- //
- if (m_taintsize != _size)
- changesize(timestep);
- //
- if (m_taintshape)
- changeshape(timestep);
- //
- if (m_taintforce)
- changeAddForce(timestep);
- if (m_taintdisable)
- changedisable(timestep);
- if (m_taintselected != m_isSelected)
- changeSelectedStatus(timestep);
- if (m_taintVelocity != PhysicsVector.Zero)
- changevelocity(timestep);
- if (m_taintparent != _parent)
- changelink(timestep);
- if (m_taintCollidesWater != m_collidesWater)
- changefloatonwater(timestep);
- }
- else
- {
- m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil.");
- }
- }
- private void changelink(float timestep)
- {
-
- if (_parent == null && m_taintparent != null)
- {
- if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
- {
- OdePrim obj = (OdePrim)m_taintparent;
- if (obj.Body != (IntPtr)0 && Body != (IntPtr)0)
- {
- _linkJointGroup = d.JointGroupCreate(0);
- m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
- d.JointAttach(m_linkJoint, obj.Body, Body);
- d.JointSetFixed(m_linkJoint);
- }
- }
- }
- else if (_parent != null && m_taintparent == null)
- {
- if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
- d.JointGroupDestroy(_linkJointGroup);
- _linkJointGroup = (IntPtr)0;
- m_linkJoint = (IntPtr)0;
- }
-
- _parent = m_taintparent;
- }
- private void changeSelectedStatus(float timestep)
- {
-
- if (m_taintselected)
- {
- m_collisionCategories = CollisionCategories.Selected;
- m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
- // We do the body disable soft twice because 'in theory' a collision could have happened
- // in between the disabling and the collision properties setting
- // which would wake the physical body up from a soft disabling and potentially cause it to fall
- // through the ground.
- if (m_isphysical)
- {
- disableBodySoft();
- }
- if (prim_geom != (IntPtr)0)
- {
- d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- }
- if (m_isphysical)
- {
- disableBodySoft();
- }
- }
- else
- {
-
- m_collisionCategories = CollisionCategories.Geom;
-
- if (m_isphysical)
- m_collisionCategories |= CollisionCategories.Body;
- m_collisionFlags = m_default_collisionFlags;
- if (m_collidesLand)
- m_collisionFlags |= CollisionCategories.Land;
- if (m_collidesWater)
- m_collisionFlags |= CollisionCategories.Water;
- if (prim_geom != (IntPtr)0)
- {
- d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- }
- if (m_isphysical)
- {
- d.BodySetLinearVel(Body, 0f, 0f, 0f);
- enableBodySoft();
- }
-
- }
-
- resetCollisionAccounting();
- m_isSelected = m_taintselected;
- }
- public void ResetTaints()
- {
- m_taintposition = _position;
- m_taintrot = _orientation;
- m_taintPhysics = m_isphysical;
- m_taintselected = m_isSelected;
- m_taintsize = _size;
-
- m_taintshape = false;
- m_taintforce = false;
-
- m_taintdisable = false;
- m_taintVelocity = PhysicsVector.Zero;
- }
- public void changeadd(float timestep)
- {
-
-
-
- int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
- IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
- if (targetspace == IntPtr.Zero)
- targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
- m_targetSpace = targetspace;
-
- if (_mesh != null)
- {
- }
- else
- {
- if (_parent_scene.needsMeshing(_pbs))
- {
- // Don't need to re-enable body.. it's done in SetMesh
- _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size);
- // createmesh returns null when it's a shape that isn't a cube.
- }
- }
- lock (OdeScene.OdeLock)
- {
- if (_mesh != null)
- {
- setMesh(_parent_scene, _mesh);
- }
- else
- {
- if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
- {
- if (((_size.X / 2f) > 0f))
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- try
- {
- SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
- }
- catch (System.AccessViolationException)
- {
- m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
- ode.dunlock(_parent_scene.world);
- return;
- }
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- try
- {
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- catch (System.AccessViolationException)
- {
- m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
- ode.dunlock(_parent_scene.world);
- return;
- }
- }
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- try
- {
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- catch (System.AccessViolationException)
- {
- m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
- ode.dunlock(_parent_scene.world);
- return;
- }
- }
- }
- //else if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
- //{
- //Cyllinder
- //if (_size.X == _size.Y)
- //{
- //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
- //}
- //else
- //{
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- //}
- //}
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- try
- {
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- catch (System.AccessViolationException)
- {
- m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
- ode.dunlock(_parent_scene.world);
- return;
- }
- }
- }
- if (prim_geom != (IntPtr) 0)
- {
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- }
- if (m_isphysical && Body == (IntPtr)0)
- {
- enableBody();
- }
- }
-
- _parent_scene.geom_name_map[prim_geom] = this.m_primName;
- _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
- changeSelectedStatus(timestep);
- m_taintadd = false;
- }
- public void changemove(float timestep)
- {
-
- if (m_isphysical)
- {
- // This is a fallback.. May no longer be necessary.
- if (Body == (IntPtr) 0)
- enableBody();
- //Prim auto disable after 20 frames,
- //if you move it, re-enable the prim manually.
- if (_parent != null)
- {
- if (m_linkJoint != (IntPtr)0)
- {
- d.JointDestroy(m_linkJoint);
- m_linkJoint = (IntPtr)0;
- }
- }
- d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
- if (_parent != null)
- {
- OdePrim odParent = (OdePrim)_parent;
- if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0)
- {
- m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
- d.JointAttach(m_linkJoint, Body, odParent.Body);
- d.JointSetFixed(m_linkJoint);
- }
- }
- d.BodyEnable(Body);
-
- }
- else
- {
- string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
- int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
- m_targetSpace = tempspace;
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- if (prim_geom != (IntPtr) 0)
- {
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- d.SpaceAdd(m_targetSpace, prim_geom);
- }
- }
-
- changeSelectedStatus(timestep);
-
- resetCollisionAccounting();
- m_taintposition = _position;
- }
- public void Move(float timestep)
- {
- float fx = 0;
- float fy = 0;
- float fz = 0;
- if (IsPhysical && Body != (IntPtr)0 && !m_isSelected)
- {
- float PID_D = 2200.0f;
- //float PID_P = 900.0f;
-
-
- float m_mass = CalculateMass();
-
- fz = 0f;
- //m_log.Info(m_collisionFlags.ToString());
-
- if (m_buoyancy != 0)
- {
-
- if (m_buoyancy > 0)
- {
- fz = ((9.8f * m_buoyancy) * m_mass);
-
- //d.Vector3 l_velocity = d.BodyGetLinearVel(Body);
- //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (9.8f * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString());
- }
- else
- {
- fz = (-1 * ((9.8f * (-1 * m_buoyancy)) * m_mass));
- }
-
- }
- if (m_usePID)
- {
- // If we're using the PID controller, then we have no gravity
- fz = ((9.8f) * this.Mass );
- // no lock; for now it's only called from within Simulate()
- // If the PID Controller isn't active then we set our force
- // calculating base velocity to the current position
- if (System.Environment.OSVersion.Platform == PlatformID.Unix)
- {
- PID_D = 3200.0f;
- //PID_P = 1400.0f;
- }
- else
- {
- PID_D = 2200.0f;
- //PID_P = 900.0f;
- }
- PID_D = 1.0f;
- //PID_P = 1.0f;
-
- //PidStatus = true;
- PhysicsVector vec = new PhysicsVector();
- d.Vector3 vel = d.BodyGetLinearVel(Body);
-
- d.Vector3 pos = d.BodyGetPosition(Body);
- _target_velocity =
- new PhysicsVector(
- (m_PIDTarget.X - pos.X) / m_PIDTau,
- (m_PIDTarget.Y - pos.Y) / m_PIDTau,
- (m_PIDTarget.Z - pos.Z) / m_PIDTau
- );
- // if velocity is zero, use position control; otherwise, velocity control
-
- if (_target_velocity.IsIdentical(PhysicsVector.Zero,0.1f))
- {
- // keep track of where we stopped. No more slippin' & slidin'
-
-
- // We only want to deactivate the PID Controller if we think we want to have our surrogate
- // react to the physics scene by moving it's position.
- // Avatar to Avatar collisions
- // Prim to avatar collisions
-
- //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
- //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
- //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
- d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
- d.BodySetLinearVel(Body, 0, 0, 0);
- d.BodyAddForce(Body, 0, 0, fz);
- return;
- }
- else
- {
-
- _zeroFlag = false;
-
- // We're flying and colliding with something
- fx = ((_target_velocity.X / m_PIDTau) - vel.X) * (PID_D / 6);
- fy = ((_target_velocity.Y / m_PIDTau) - vel.Y) * (PID_D / 6);
-
-
-
- // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
- fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
- }
- }
- fx *= m_mass;
- fy *= m_mass;
- //fz *= m_mass;
-
- //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
- if (fx != 0 || fy != 0 || fz != 0)
- {
- //m_taintdisable = true;
- //base.RaiseOutOfBounds(Position);
- //d.BodySetLinearVel(Body, fx, fy, 0f);
- d.BodyAddForce(Body, fx, fy, fz);
- }
- }
- else
- {
- _zeroPosition = d.BodyGetPosition(Body);
- return;
- }
- }
- public void rotate(float timestep)
- {
-
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- if (m_isphysical && Body != (IntPtr) 0)
- {
- d.BodySetQuaternion(Body, ref myrot);
- }
-
- resetCollisionAccounting();
- m_taintrot = _orientation;
- }
- private void resetCollisionAccounting()
- {
- m_collisionscore = 0;
- m_interpenetrationcount = 0;
- m_disabled = false;
- }
- public void changedisable(float timestep)
- {
-
- m_disabled = true;
- if (Body != (IntPtr)0)
- {
- d.BodyDisable(Body);
- Body = (IntPtr)0;
- }
-
- m_taintdisable = false;
- }
- public void changePhysicsStatus(float timestep)
- {
-
- if (m_isphysical == true)
- {
- if (Body == (IntPtr)0)
- {
- enableBody();
- }
- }
- else
- {
- if (Body != (IntPtr)0)
- {
- disableBody();
- }
- }
- changeSelectedStatus(timestep);
- resetCollisionAccounting();
- m_taintPhysics = m_isphysical;
- }
- public void changesize(float timestamp)
- {
-
- //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom))
- //{
- // m_taintsize = _size;
- //return;
- //}
- string oldname = _parent_scene.geom_name_map[prim_geom];
-
- // Cleanup of old prim geometry
- if (_mesh != null)
- {
- // Cleanup meshing here
- }
- //kill body to rebuild
- if (IsPhysical && Body != (IntPtr) 0)
- {
- disableBody();
- }
- if (d.SpaceQuery(m_targetSpace, prim_geom))
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- d.SpaceRemove(m_targetSpace, prim_geom);
- }
- d.GeomDestroy(prim_geom);
- prim_geom = (IntPtr)0;
- // we don't need to do space calculation because the client sends a position update also.
- // Construction of new prim
- if (_parent_scene.needsMeshing(_pbs))
- {
- // Don't need to re-enable body.. it's done in SetMesh
- IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
- // createmesh returns null when it's a shape that isn't a cube.
- if (mesh != null)
- {
- setMesh(_parent_scene, mesh);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
- if (IsPhysical && Body == (IntPtr)0)
- {
- // Re creates body on size.
- // EnableBody also does setMass()
- enableBody();
- d.BodyEnable(Body);
- }
- }
- else
- {
- if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
- {
- if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
- }
- else
- {
- m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
- //{
- //Cyllinder
- //if (_size.X == _size.Y)
- //{
- // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
- //}
- //else
- //{
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- //}
- //}
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- }
- }
- else
- {
- if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
- //{
- //Cyllinder
- //if (_size.X == _size.Y)
- //{
- //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
- //}
- //else
- //{
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- //}
- //}
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
- if (IsPhysical && Body == (IntPtr) 0)
- {
- // Re creates body on size.
- // EnableBody also does setMass()
- enableBody();
- d.BodyEnable(Body);
- }
- }
- _parent_scene.geom_name_map[prim_geom] = oldname;
- changeSelectedStatus(timestamp);
- resetCollisionAccounting();
- m_taintsize = _size;
- }
- public void changefloatonwater(float timestep)
- {
- m_collidesWater = m_taintCollidesWater;
- if (prim_geom != (IntPtr)0)
- {
- if (m_collidesWater)
- {
- m_collisionFlags |= CollisionCategories.Water;
- }
- else
- {
- m_collisionFlags &= ~CollisionCategories.Water;
- }
- d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
- }
- }
- public void changeshape(float timestamp)
- {
-
- string oldname = _parent_scene.geom_name_map[prim_geom];
- // Cleanup of old prim geometry and Bodies
- if (IsPhysical && Body != (IntPtr) 0)
- {
- disableBody();
- }
- d.GeomDestroy(prim_geom);
- prim_geom = (IntPtr) 0;
- // we don't need to do space calculation because the client sends a position update also.
- // Construction of new prim
- if (_parent_scene.needsMeshing(_pbs))
- {
- // Don't need to re-enable body.. it's done in SetMesh
- IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
- // createmesh returns null when it's a shape that isn't a cube.
- if (mesh != null)
- {
- setMesh(_parent_scene, mesh);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
- if (IsPhysical && Body == (IntPtr)0)
- {
- // Re creates body on size.
- // EnableBody also does setMass()
- enableBody();
-
- }
- }
- else
- {
- if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
- {
- if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
- }
- else
- {
- m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
- //{
- //Cyllinder
- //if (_size.X == _size.Y)
- //{
- // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
- //}
- //else
- //{
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- //}
- //}
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- }
- }
- else
- {
- if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
- }
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- }
- //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
- //{
- //Cyllinder
- //if (_size.X == _size.Y)
- //{
- //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
- //}
- //else
- //{
- //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- //}
- //}
- else
- {
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
- }
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
- if (IsPhysical && Body == (IntPtr)0)
- {
- // Re creates body on size.
- // EnableBody also does setMass()
- enableBody();
- d.BodyEnable(Body);
- }
- }
-
- _parent_scene.geom_name_map[prim_geom] = oldname;
- changeSelectedStatus(timestamp);
- resetCollisionAccounting();
- m_taintshape = false;
- }
- public void changeAddForce(float timestamp)
- {
- if (!m_isSelected)
- {
-
- lock (m_forcelist)
- {
- //m_log.Info("[PHYSICS]: dequeing forcelist");
- if (IsPhysical)
- {
- PhysicsVector iforce = new PhysicsVector();
- for (int i = 0; i < m_forcelist.Count; i++)
- {
- iforce = iforce + (m_forcelist[i] * 100);
- }
- d.BodyEnable(Body);
- d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
- }
- m_forcelist.Clear();
- }
- m_collisionscore = 0;
- m_interpenetrationcount = 0;
- }
- m_taintforce = false;
- }
- private void changevelocity(float timestep)
- {
- if (!m_isSelected)
- {
-
- System.Threading.Thread.Sleep(20);
- if (IsPhysical)
- {
- if (Body != (IntPtr)0)
- {
- d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
- }
- }
-
- //resetCollisionAccounting();
- }
- m_taintVelocity = PhysicsVector.Zero;
- }
- public override bool IsPhysical
- {
- get { return m_isphysical; }
- set { m_isphysical = value; }
- }
- public void setPrimForRemoval()
- {
- m_taintremove = true;
- }
- public override bool Flying
- {
- get { return false; //no flying prims for you
- }
- set { }
- }
- public override bool IsColliding
- {
- get { return iscolliding; }
- set { iscolliding = value; }
- }
- public override bool CollidingGround
- {
- get { return false; }
- set { return; }
- }
- public override bool CollidingObj
- {
- get { return false; }
- set { return; }
- }
- public override bool ThrottleUpdates
- {
- get { return m_throttleUpdates; }
- set { m_throttleUpdates = value; }
- }
- public override bool Stopped
- {
- get { return _zeroFlag; }
- }
- public override PhysicsVector Position
- {
- get { return _position; }
- set { _position = value;
- //m_log.Info("[PHYSICS]: " + _position.ToString());
- }
- }
- public override PhysicsVector Size
- {
- get { return _size; }
- set { _size = value; }
- }
- public override float Mass
- {
- get { return CalculateMass(); }
- }
- public override PhysicsVector Force
- {
- get { return PhysicsVector.Zero; }
- }
- public override PhysicsVector CenterOfMass
- {
- get { return PhysicsVector.Zero; }
- }
- public override PhysicsVector GeometricCenter
- {
- get { return PhysicsVector.Zero; }
- }
- public override PrimitiveBaseShape Shape
- {
- set {
- _pbs = value;
- m_taintshape = true;
- }
- }
- public override PhysicsVector Velocity
- {
- get
- {
- // Averate previous velocity with the new one so
- // client object interpolation works a 'little' better
- PhysicsVector returnVelocity = new PhysicsVector();
- returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
- returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
- returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
- return returnVelocity;
- }
- set {
- _velocity = value;
-
- m_taintVelocity = value;
- _parent_scene.AddPhysicsActorTaint(this);
-
-
- }
- }
- public override float CollisionScore
- {
- get { return m_collisionscore; }
- }
- public override bool Kinematic
- {
- get { return false; }
- set { }
- }
- public override Quaternion Orientation
- {
- get { return _orientation; }
- set { _orientation = value; }
- }
- public override PhysicsVector Acceleration
- {
- get { return _acceleration; }
- }
- public void SetAcceleration(PhysicsVector accel)
- {
- _acceleration = accel;
- }
- public override void AddForce(PhysicsVector force)
- {
- m_forcelist.Add(force);
- m_taintforce = true;
- //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
- }
- public override PhysicsVector RotationalVelocity
- {
- get {
- PhysicsVector pv = new PhysicsVector(0, 0, 0);
- if (_zeroFlag)
- return pv;
- m_lastUpdateSent = false;
-
- if (m_rotationalVelocity.IsIdentical(pv, 0.2f))
- return pv;
- return m_rotationalVelocity;
- }
- set { m_rotationalVelocity = value; }
- }
- public override void CrossingFailure()
- {
- m_crossingfailures++;
- if (m_crossingfailures > 5)
- {
- base.RaiseOutOfBounds(_position);
- return;
- }
- else if (m_crossingfailures == 5)
- {
- m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
- }
- }
- public override float Buoyancy
- {
- get { return m_buoyancy; }
- set { m_buoyancy = value; }
- }
- public override void link(PhysicsActor obj)
- {
- m_taintparent = obj;
- }
- public override void delink()
- {
- m_taintparent = null;
- }
- public void UpdatePositionAndVelocity()
- {
- // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
- if (_parent != null)
- {
- }
- else
- {
- PhysicsVector pv = new PhysicsVector(0, 0, 0);
- bool lastZeroFlag = _zeroFlag;
- if (Body != (IntPtr)0)
- {
- d.Vector3 vec = d.BodyGetPosition(Body);
- d.Quaternion ori = d.BodyGetQuaternion(Body);
- d.Vector3 vel = d.BodyGetLinearVel(Body);
- d.Vector3 rotvel = d.BodyGetAngularVel(Body);
-
- PhysicsVector l_position = new PhysicsVector();
- // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
- //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
- //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
- //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
- //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
- m_lastposition = _position;
- l_position.X = vec.X;
- l_position.Y = vec.Y;
- l_position.Z = vec.Z;
- if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f)
- {
- //base.RaiseOutOfBounds(l_position);
- if (m_crossingfailures < 5)
- {
- _position = l_position;
- //_parent_scene.remActivePrim(this);
- base.RequestPhysicsterseUpdate();
- return;
- }
- else
- {
- base.RaiseOutOfBounds(l_position);
- return;
- }
- }
- if (l_position.Z < 0)
- {
- // This is so prim that get lost underground don't fall forever and suck up
- //
- // Sim resources and memory.
- // Disables the prim's movement physics....
- // It's a hack and will generate a console message if it fails.
- //IsPhysical = false;
- base.RaiseOutOfBounds(_position);
-
- _acceleration.X = 0;
- _acceleration.Y = 0;
- _acceleration.Z = 0;
- _velocity.X = 0;
- _velocity.Y = 0;
- _velocity.Z = 0;
- m_rotationalVelocity.X = 0;
- m_rotationalVelocity.Y = 0;
- m_rotationalVelocity.Z = 0;
- base.RequestPhysicsterseUpdate();
- m_throttleUpdates = false;
- throttleCounter = 0;
- _zeroFlag = true;
- //outofBounds = true;
- }
- if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
- && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
- && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02))
- {
- _zeroFlag = true;
- m_throttleUpdates = false;
- }
- else
- {
- //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
- _zeroFlag = false;
- }
- if (_zeroFlag)
- {
- // Supposedly this is supposed to tell SceneObjectGroup that
- // no more updates need to be sent..
- // but it seems broken.
- _velocity.X = 0.0f;
- _velocity.Y = 0.0f;
- _velocity.Z = 0.0f;
- _acceleration.X = 0;
- _acceleration.Y = 0;
- _acceleration.Z = 0;
- //_orientation.w = 0f;
- //_orientation.x = 0f;
- //_orientation.y = 0f;
- //_orientation.z = 0f;
- m_rotationalVelocity.X = 0;
- m_rotationalVelocity.Y = 0;
- m_rotationalVelocity.Z = 0;
- if (!m_lastUpdateSent)
- {
- m_throttleUpdates = false;
- throttleCounter = 0;
- m_rotationalVelocity = pv;
- base.RequestPhysicsterseUpdate();
- m_lastUpdateSent = true;
- }
- }
- else
- {
- if (lastZeroFlag != _zeroFlag)
- base.RequestPhysicsterseUpdate();
- m_lastVelocity = _velocity;
- _position = l_position;
- _velocity.X = vel.X;
- _velocity.Y = vel.Y;
- _velocity.Z = vel.Z;
-
- _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
- _acceleration = new PhysicsVector(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
- //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
-
- if (_velocity.IsIdentical(pv, 0.5f))
- {
- m_rotationalVelocity = pv;
- }
- else
- {
- m_rotationalVelocity.setValues(rotvel.X, rotvel.Y, rotvel.Z);
- }
- //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
- _orientation.w = ori.W;
- _orientation.x = ori.X;
- _orientation.y = ori.Y;
- _orientation.z = ori.Z;
- m_lastUpdateSent = false;
- if (!m_throttleUpdates || throttleCounter > 15)
- {
- base.RequestPhysicsterseUpdate();
- }
- else
- {
- throttleCounter++;
- }
- }
- m_lastposition = l_position;
- }
- else
- {
- // Not a body.. so Make sure the client isn't interpolating
- _velocity.X = 0;
- _velocity.Y = 0;
- _velocity.Z = 0;
- _acceleration.X = 0;
- _acceleration.Y = 0;
- _acceleration.Z = 0;
- m_rotationalVelocity.X = 0;
- m_rotationalVelocity.Y = 0;
- m_rotationalVelocity.Z = 0;
- _zeroFlag = true;
- }
- }
- }
- public override bool FloatOnWater
- {
- set {
- m_taintCollidesWater = value;
- _parent_scene.AddPhysicsActorTaint(this);
- }
- }
- public override void SetMomentum(PhysicsVector momentum)
- {
- }
- public override PhysicsVector PIDTarget { set { m_PIDTarget = value; ; } }
- public override bool PIDActive { set { m_usePID = value; } }
- public override float PIDTau { set { m_PIDTau = (value * 0.6f); } }
- }
- }
|