123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167 |
- /*
- * 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 Axiom.Math;
- using Ode.NET;
- using OpenSim.Framework;
- using OpenSim.Region.Physics.Manager;
- using System.Collections.Generic; // rex
- using System.Runtime.InteropServices; // rex
- using RexDotMeshLoader; // rex
- using OpenSim.Framework.Console; // rex
- using libsecondlife; // rex
- namespace OpenSim.Region.Physics.OdePlugin
- {
- // rex, new class
- public class OdeCollisionMesh : IMesh
- {
- public float[] vertexListOrig;
- public int[] indexListOrig;
- public float[] vertexList;
- public int[] indexList;
- public GCHandle gchVertexList;
- public GCHandle gchIndexList;
- public LLVector3 BoundsMin = new LLVector3();
- public LLVector3 BoundsMax = new LLVector3();
- public bool m_BoundsScaling;
- public OdeCollisionMesh(int vVertexCount, int vIndexCount)
- {
- vertexList = new float[vVertexCount];
- gchVertexList = GCHandle.Alloc(vertexList, GCHandleType.Pinned);
- vertexListOrig = new float[vVertexCount];
- indexList = new int[vIndexCount];
- gchIndexList = GCHandle.Alloc(indexList, GCHandleType.Pinned);
- indexListOrig = new int[vIndexCount];
- }
- public void FreeLists()
- {
- gchVertexList.Free();
- gchIndexList.Free();
- }
- public List<PhysicsVector> getVertexList()
- {
- return null;
- }
- public int[] getIndexListAsInt()
- {
- return indexList;
- }
- public int[] getIndexListAsIntLocked()
- {
- return indexList;
- }
- public float[] getVertexListAsFloatLocked()
- {
- return vertexList;
- }
- }
- public class OdePrim : PhysicsActor
- {
- 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 Quaternion _orientation;
- private PhysicsVector m_taintposition;
- private PhysicsVector m_taintsize;
- private Quaternion m_taintrot;
- private bool m_taintshape = false;
- private bool m_taintPhysics = false;
- public bool m_taintremove = false;
- private IMesh _mesh;
- private PrimitiveBaseShape _pbs;
- private OdeScene _parent_scene;
- public IntPtr m_targetSpace = (IntPtr) 0;
- public IntPtr prim_geom;
- public IntPtr _triMeshData;
- private bool iscolliding = false;
- private bool m_isphysical = false;
- private bool m_throttleUpdates = false;
- private int throttleCounter = 0;
- 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 int debugcounter = 0;
- private bool m_DotMeshCollision = false; // rex
- public bool m_BoundsScalingUpdate = false; // rex
- private bool m_PrimVolume = false; // rex
- public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size,
- Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, uint localID)
- {
- m_localID = localID; // rex
- _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;
- }
- _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 = targetSpace;
- 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;
- lock (OdeScene.OdeLock)
- {
- if (mesh != null)
- {
- setMesh(parent_scene, mesh);
- }
- else
- {
- 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 = rotation.w;
- myrot.X = rotation.x;
- myrot.Y = rotation.y;
- myrot.Z = rotation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- if (m_isphysical && Body == (IntPtr) 0)
- {
- enableBody();
- }
- parent_scene.geom_name_map[prim_geom] = primName;
- parent_scene.actor_name_map[prim_geom] = (PhysicsActor) this;
- // don't do .add() here; old geoms get recycled with the same hash
- }
- }
- // rex, modified function, m_PrimVolume added
- public override int PhysicsActorType
- {
- get
- {
- if (m_PrimVolume)
- return (int)ActorTypes.PrimVolume;
- else
- return (int)ActorTypes.Prim;
- }
- set
- {
- if (value == (int)ActorTypes.PrimVolume)
- m_PrimVolume = true;
- else
- m_PrimVolume = false;
- }
- }
- public override bool SetAlwaysRun
- {
- get { return false; }
- set { return; }
- }
- 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);
- d.BodySetAutoDisableFlag(Body, true);
- d.BodySetAutoDisableSteps(Body, 20);
- _parent_scene.addActivePrim(this);
- }
- 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;
- 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);
- }
- // Mass = density * volume
- returnMass = m_density*volume;
- return returnMass;
- }
- public void setMass()
- {
- if (Body != (IntPtr) 0)
- {
- d.MassSetBoxTotal(out pMass, CalculateMass(), _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.
- if (Body != (IntPtr) 0)
- {
- _parent_scene.remActivePrim(this);
- d.BodyDestroy(Body);
- Body = (IntPtr) 0;
- }
- }
- public void setMesh(OdeScene parent_scene, IMesh mesh)
- {
- //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);
- // rex, del old trimeshdata
- if (_triMeshData != (IntPtr)0)
- d.GeomTriMeshDataDestroy(_triMeshData);
- _mesh = mesh; // rex, end
- _triMeshData = d.GeomTriMeshDataCreate();
- d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
- 3*sizeof (int));
- d.GeomTriMeshDataPreprocess(_triMeshData);
- prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
- if (IsPhysical && Body == (IntPtr) 0)
- {
- // Recreate the body
- enableBody();
- }
- }
- public void ProcessTaints(float timestep)
- {
- if (m_taintposition != _position)
- Move(timestep);
- if (m_taintrot != _orientation)
- rotate(timestep);
- //
- if (m_taintPhysics != m_isphysical)
- changePhysicsStatus(timestep);
- //
- if (m_taintsize != _size)
- changesize(timestep);
- if (m_BoundsScalingUpdate) // rex
- changesize(timestep);
- //
- if (m_taintshape)
- changeshape(timestep);
- //
- }
- public void Move(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.
- d.BodyEnable(Body);
- d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
- }
- else
- {
- string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
- int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
- m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.SpaceAdd(m_targetSpace, prim_geom);
- }
- m_taintposition = _position;
- }
- // rex, function changed
- public void rotate(float timestep)
- {
- d.Quaternion myrot = new d.Quaternion();
- if (m_DotMeshCollision && _mesh != null) // rex, setting rot for collision 3d model
- {
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
- Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
- Quaternion mytemprot = _orientation * meshRotA * meshRotB;
-
- myrot.W = mytemprot.w;
- myrot.X = mytemprot.x;
- myrot.Y = mytemprot.y;
- myrot.Z = mytemprot.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- }
- else
- {
- 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);
- }
- m_taintrot = _orientation;
- }
- public void changePhysicsStatus(float timestap)
- {
- if (m_isphysical == true)
- {
- if (Body == (IntPtr) 0)
- {
- enableBody();
- }
- }
- else
- {
- if (Body != (IntPtr) 0)
- {
- disableBody();
- }
- }
- m_taintPhysics = m_isphysical;
- }
- // rex, function changed
- public void changesize(float timestamp)
- {
- 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))
- {
- d.SpaceRemove(m_targetSpace, prim_geom);
- }
- d.GeomDestroy(prim_geom);
- // we don't need to do space calculation because the client sends a position update also.
- if (m_DotMeshCollision && _mesh != null) // rex, scaling dotmesh models
- {
- float[] scalefactor = new float[3];
- int vertindex = 0;
- OdeCollisionMesh mesh = _mesh as OdeCollisionMesh;
- LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z);
- if (mesh.m_BoundsScaling)
- {
- LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin;
- if (boundssize.X != 0)
- scalingvector.X /= boundssize.X;
- if (boundssize.Y != 0)
- scalingvector.Z /= boundssize.Y;
- if (boundssize.Z != 0)
- scalingvector.Y /= boundssize.Z;
- }
- scalefactor[0] = scalingvector.X;
- scalefactor[1] = scalingvector.Z;
- scalefactor[2] = scalingvector.Y;
- for (int i = 0; i < mesh.vertexList.GetLength(0); i++)
- {
- mesh.vertexList[i] = mesh.vertexListOrig[i] * scalefactor[vertindex];
- vertindex++;
- if (vertindex > 2)
- vertindex = 0;
- }
- for (int i = 0; i < mesh.indexList.GetLength(0); i++)
- mesh.indexList[i] = mesh.indexListOrig[i];
- setMesh(_parent_scene, mesh);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
- Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
- Quaternion mytemprot = _orientation * meshRotA * meshRotB;
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = mytemprot.w;
- myrot.X = mytemprot.x;
- myrot.Y = mytemprot.y;
- myrot.Z = mytemprot.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- if (IsPhysical && Body == (IntPtr)0)
- {
- // Re creates body on size.
- // EnableBody also does setMass()
- enableBody();
- d.BodyEnable(Body);
- }
- } // rex, end scaling
- // Construction of new prim
- else 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);
- }
- else
- {
- 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
- {
- 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);
- //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;
- m_taintsize = _size;
- m_BoundsScalingUpdate = false; // rex
- }
- 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);
- if (_mesh != null)
- {
- d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
- }
- // Construction of new prim
- if (_parent_scene.needsMeshing(_pbs))
- {
- IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
- if (mesh != null)
- {
- setMesh(_parent_scene, mesh);
- }
- else
- {
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- }
- }
- else
- {
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
- }
- if (IsPhysical && Body == (IntPtr) 0)
- {
- //re-create new body
- enableBody();
- }
- else
- {
- 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);
- }
- _parent_scene.geom_name_map[prim_geom] = oldname;
- m_taintshape = false;
- }
- 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 PhysicsVector Position
- {
- get { return _position; }
- set { _position = value; }
- }
- 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; }
- }
- 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; }
- }
- 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)
- {
- }
- public override PhysicsVector RotationalVelocity
- {
- get { return m_rotationalVelocity; }
- set { m_rotationalVelocity = value; }
- }
- public void UpdatePositionAndVelocity()
- {
- // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
- 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 (vec.Y < 0.0f) vec.Y = 0.0f;
- if (vec.X > 255.95f) vec.X = 255.95f;
- if (vec.Y > 255.95f) vec.Y = 255.95f;
- m_lastposition = _position;
- l_position.X = vec.X;
- l_position.Y = vec.Y;
- l_position.Z = vec.Z;
- 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);
- _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;
- }
- 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;
- //_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;
- base.RequestPhysicsterseUpdate();
- m_lastUpdateSent = true;
- }
- }
- else
- {
- m_lastVelocity = _velocity;
- _position = l_position;
- _velocity.X = vel.X;
- _velocity.Y = vel.Y;
- _velocity.Z = vel.Z;
- m_rotationalVelocity.X = rotvel.X;
- m_rotationalVelocity.Y = rotvel.Y;
- m_rotationalVelocity.Z = 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;
- m_rotationalVelocity.X = 0;
- m_rotationalVelocity.Y = 0;
- m_rotationalVelocity.Z = 0;
- _zeroFlag = true;
- }
- }
- public override void SetMomentum(PhysicsVector momentum)
- {
- }
- // rex, new function.
- // This function should be called only outside of simulation loop -> OdeLock used.
- public override void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh)
- {
- float[] tempVertexList;
- float[] tempBounds;
- int[] tempIndexList;
- string errorMessage;
- float[] scalefactor = new float[3];
- int vertindex = 0;
- lock (OdeScene.OdeLock)
- {
- // 1. Get rid of old mesh
- m_DotMeshCollision = false;
- if (_mesh != null)
- {
- if ((OdeCollisionMesh)_mesh != null)
- (_mesh as OdeCollisionMesh).FreeLists();
- _mesh = null;
- }
- // 2. Try to load new colmesh
- OdeCollisionMesh mesh = null;
- if (vData != null)
- {
- DotMeshLoader.ReadDotMeshModel(vData, out tempVertexList, out tempIndexList, out tempBounds, out errorMessage);
- if (tempVertexList != null && tempIndexList != null)
- {
- mesh = new OdeCollisionMesh(tempVertexList.GetLength(0), tempIndexList.GetLength(0));
- mesh.m_BoundsScaling = vbScaleMesh;
- mesh.BoundsMin.X = tempBounds[0];
- mesh.BoundsMin.Y = tempBounds[1];
- mesh.BoundsMin.Z = tempBounds[2];
- mesh.BoundsMax.X = tempBounds[3];
- mesh.BoundsMax.Y = tempBounds[4];
- mesh.BoundsMax.Z = tempBounds[5];
- LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z);
- if (vbScaleMesh)
- {
- LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin;
- if (boundssize.X != 0)
- scalingvector.X /= boundssize.X;
- if (boundssize.Y != 0)
- scalingvector.Z /= boundssize.Y;
- if (boundssize.Z != 0)
- scalingvector.Y /= boundssize.Z;
- }
- scalefactor[0] = scalingvector.X;
- scalefactor[1] = scalingvector.Z;
- scalefactor[2] = scalingvector.Y;
- for (int i = 0; i < tempVertexList.GetLength(0); i++)
- {
- mesh.vertexListOrig[i] = tempVertexList[i];
- mesh.vertexList[i] = tempVertexList[i] * scalefactor[vertindex];
-
- vertindex++;
- if (vertindex > 2)
- vertindex = 0;
- }
- for (int i = 0; i < tempIndexList.GetLength(0); i++)
- {
- mesh.indexListOrig[i] = tempIndexList[i];
- mesh.indexList[i] = tempIndexList[i];
- }
- }
- else
- MainLog.Instance.Error("PHYSICS", "Error importing mesh:" + MeshName + ", " + errorMessage);
- }
- // 3. If mesh is null, must create the default collisionbox
- if (mesh == null)
- {
- CreateDefaultCollision();
- return;
- }
- // 4. If mesh loaded, use it
- string oldname = _parent_scene.geom_name_map[prim_geom];
- m_DotMeshCollision = true;
- if (IsPhysical && Body != (IntPtr)0)
- disableBody();
- if (prim_geom != (IntPtr)0)
- {
- if (d.SpaceQuery(m_targetSpace, prim_geom))
- {
- d.SpaceRemove(m_targetSpace, prim_geom);
- }
- d.GeomDestroy(prim_geom);
- }
- setMesh(_parent_scene, mesh);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
- Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
- Quaternion mytemprot = _orientation * meshRotA * meshRotB;
-
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = mytemprot.w;
- myrot.X = mytemprot.x;
- myrot.Y = mytemprot.y;
- myrot.Z = mytemprot.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
- _parent_scene.geom_name_map[prim_geom] = oldname;
- }
- }
- // rex, function added
- private void CreateDefaultCollision()
- {
- 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))
- {
- d.SpaceRemove(m_targetSpace, prim_geom);
- }
- d.GeomDestroy(prim_geom);
- // 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);
- }
- else
- {
- 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
- {
- 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);
- //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;
- }
- // rex, new function
- public override void SetBoundsScaling(bool vbScaleMesh)
- {
- if (m_DotMeshCollision && _mesh != null)
- {
- (_mesh as OdeCollisionMesh).m_BoundsScaling = vbScaleMesh;
- m_BoundsScalingUpdate = true;
- }
- }
- }
- }
|