UbitODE plugin initial commit
parent
9c6ba8d18f
commit
815f3af1d7
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSimulator 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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Information about this assembly is defined by the following
|
||||||
|
// attributes.
|
||||||
|
//
|
||||||
|
// change them to the information which is associated with the assembly
|
||||||
|
// you compile.
|
||||||
|
|
||||||
|
[assembly : AssemblyTitle("OdePlugin")]
|
||||||
|
[assembly : AssemblyDescription("Ubit Variation")]
|
||||||
|
[assembly : AssemblyConfiguration("")]
|
||||||
|
[assembly : AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly : AssemblyProduct("OdePlugin")]
|
||||||
|
[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
|
||||||
|
[assembly : AssemblyTrademark("")]
|
||||||
|
[assembly : AssemblyCulture("")]
|
||||||
|
|
||||||
|
// This sets the default COM visibility of types in the assembly to invisible.
|
||||||
|
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
|
||||||
|
|
||||||
|
[assembly : ComVisible(false)]
|
||||||
|
|
||||||
|
// The assembly version has following format :
|
||||||
|
//
|
||||||
|
// Major.Minor.Build.Revision
|
||||||
|
//
|
||||||
|
// You can specify all values by your own or you can build default build and revision
|
||||||
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
|
[assembly : AssemblyVersion("0.6.5.*")]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,630 @@
|
||||||
|
/*
|
||||||
|
* Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
|
||||||
|
* ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
|
||||||
|
* ODEPrim.cs contains methods dealing with Prim editing, Prim
|
||||||
|
* characteristics and Kinetic motion.
|
||||||
|
* ODEDynamics.cs contains methods dealing with Prim Physical motion
|
||||||
|
* (dynamics) and the associated settings. Old Linear and angular
|
||||||
|
* motors for dynamic motion have been replace with MoveLinear()
|
||||||
|
* and MoveAngular(); 'Physical' is used only to switch ODE dynamic
|
||||||
|
* simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
|
||||||
|
* switch between 'VEHICLE' parameter use and general dynamics
|
||||||
|
* settings use.
|
||||||
|
*
|
||||||
|
* 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 OpenSimulator 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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Ode.NET;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
{
|
||||||
|
public class ODEDynamics
|
||||||
|
{
|
||||||
|
public Vehicle Type
|
||||||
|
{
|
||||||
|
get { return m_type; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntPtr Body
|
||||||
|
{
|
||||||
|
get { return m_body; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int frcount = 0; // Used to limit dynamics debug output to
|
||||||
|
// every 100th frame
|
||||||
|
|
||||||
|
// private OdeScene m_parentScene = null;
|
||||||
|
private IntPtr m_body = IntPtr.Zero;
|
||||||
|
private IntPtr m_jointGroup = IntPtr.Zero;
|
||||||
|
private IntPtr m_aMotor = IntPtr.Zero;
|
||||||
|
|
||||||
|
|
||||||
|
// Vehicle properties
|
||||||
|
private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
|
||||||
|
// private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
|
||||||
|
private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
|
||||||
|
// HOVER_TERRAIN_ONLY
|
||||||
|
// HOVER_GLOBAL_HEIGHT
|
||||||
|
// NO_DEFLECTION_UP
|
||||||
|
// HOVER_WATER_ONLY
|
||||||
|
// HOVER_UP_ONLY
|
||||||
|
// LIMIT_MOTOR_UP
|
||||||
|
// LIMIT_ROLL_ONLY
|
||||||
|
|
||||||
|
// Linear properties
|
||||||
|
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
|
||||||
|
private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
|
||||||
|
private Vector3 m_dir = Vector3.Zero; // velocity applied to body
|
||||||
|
private Vector3 m_linearFrictionTimescale = Vector3.Zero;
|
||||||
|
private float m_linearMotorDecayTimescale = 0;
|
||||||
|
private float m_linearMotorTimescale = 0;
|
||||||
|
private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
|
||||||
|
// private bool m_LinearMotorSetLastFrame = false;
|
||||||
|
// private Vector3 m_linearMotorOffset = Vector3.Zero;
|
||||||
|
|
||||||
|
//Angular properties
|
||||||
|
private Vector3 m_angularMotorDirection = Vector3.Zero;
|
||||||
|
private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero;
|
||||||
|
private Vector3 m_angularFrictionTimescale = Vector3.Zero;
|
||||||
|
private float m_angularMotorDecayTimescale = 0;
|
||||||
|
private float m_angularMotorTimescale = 0;
|
||||||
|
private Vector3 m_lastAngularVelocityVector = Vector3.Zero;
|
||||||
|
|
||||||
|
//Deflection properties
|
||||||
|
// private float m_angularDeflectionEfficiency = 0;
|
||||||
|
// private float m_angularDeflectionTimescale = 0;
|
||||||
|
// private float m_linearDeflectionEfficiency = 0;
|
||||||
|
// private float m_linearDeflectionTimescale = 0;
|
||||||
|
|
||||||
|
//Banking properties
|
||||||
|
// private float m_bankingEfficiency = 0;
|
||||||
|
// private float m_bankingMix = 0;
|
||||||
|
// private float m_bankingTimescale = 0;
|
||||||
|
|
||||||
|
//Hover and Buoyancy properties
|
||||||
|
private float m_VhoverHeight = 0f;
|
||||||
|
private float m_VhoverEfficiency = 0f;
|
||||||
|
private float m_VhoverTimescale = 0f;
|
||||||
|
private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
|
||||||
|
private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
|
||||||
|
// Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
|
||||||
|
// KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
|
||||||
|
// Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
|
||||||
|
|
||||||
|
//Attractor properties
|
||||||
|
private float m_verticalAttractionEfficiency = 0;
|
||||||
|
private float m_verticalAttractionTimescale = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
|
||||||
|
{
|
||||||
|
switch (pParam)
|
||||||
|
{
|
||||||
|
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_angularDeflectionEfficiency = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_angularDeflectionTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_angularMotorDecayTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_angularMotorTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.BANKING_EFFICIENCY:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_bankingEfficiency = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.BANKING_MIX:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_bankingMix = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.BANKING_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_bankingTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.BUOYANCY:
|
||||||
|
if (pValue < -1f) pValue = -1f;
|
||||||
|
if (pValue > 1f) pValue = 1f;
|
||||||
|
m_VehicleBuoyancy = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.HOVER_EFFICIENCY:
|
||||||
|
if (pValue < 0f) pValue = 0f;
|
||||||
|
if (pValue > 1f) pValue = 1f;
|
||||||
|
m_VhoverEfficiency = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.HOVER_HEIGHT:
|
||||||
|
m_VhoverHeight = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.HOVER_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_VhoverTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_linearDeflectionEfficiency = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
// m_linearDeflectionTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_linearMotorDecayTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_linearMotorTimescale = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
|
||||||
|
if (pValue < 0.0f) pValue = 0.0f;
|
||||||
|
if (pValue > 1.0f) pValue = 1.0f;
|
||||||
|
m_verticalAttractionEfficiency = pValue;
|
||||||
|
break;
|
||||||
|
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
|
||||||
|
if (pValue < 0.01f) pValue = 0.01f;
|
||||||
|
m_verticalAttractionTimescale = pValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// These are vector properties but the engine lets you use a single float value to
|
||||||
|
// set all of the components to the same value
|
||||||
|
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
|
||||||
|
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
|
||||||
|
break;
|
||||||
|
case Vehicle.ANGULAR_MOTOR_DIRECTION:
|
||||||
|
m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
|
||||||
|
m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_FRICTION_TIMESCALE:
|
||||||
|
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_DIRECTION:
|
||||||
|
m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
|
||||||
|
m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_OFFSET:
|
||||||
|
// m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end ProcessFloatVehicleParam
|
||||||
|
|
||||||
|
internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue)
|
||||||
|
{
|
||||||
|
switch (pParam)
|
||||||
|
{
|
||||||
|
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
|
||||||
|
m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
break;
|
||||||
|
case Vehicle.ANGULAR_MOTOR_DIRECTION:
|
||||||
|
m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_FRICTION_TIMESCALE:
|
||||||
|
m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_DIRECTION:
|
||||||
|
m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
break;
|
||||||
|
case Vehicle.LINEAR_MOTOR_OFFSET:
|
||||||
|
// m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end ProcessVectorVehicleParam
|
||||||
|
|
||||||
|
internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
|
||||||
|
{
|
||||||
|
switch (pParam)
|
||||||
|
{
|
||||||
|
case Vehicle.REFERENCE_FRAME:
|
||||||
|
// m_referenceFrame = pValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end ProcessRotationVehicleParam
|
||||||
|
|
||||||
|
internal void ProcessTypeChange(Vehicle pType)
|
||||||
|
{
|
||||||
|
Console.WriteLine("ProcessTypeChange to " + pType);
|
||||||
|
|
||||||
|
// Set Defaults For Type
|
||||||
|
m_type = pType;
|
||||||
|
switch (pType)
|
||||||
|
{
|
||||||
|
case Vehicle.TYPE_SLED:
|
||||||
|
m_linearFrictionTimescale = new Vector3(30, 1, 1000);
|
||||||
|
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
|
||||||
|
m_linearMotorDirection = Vector3.Zero;
|
||||||
|
m_linearMotorTimescale = 1000;
|
||||||
|
m_linearMotorDecayTimescale = 120;
|
||||||
|
m_angularMotorDirection = Vector3.Zero;
|
||||||
|
m_angularMotorTimescale = 1000;
|
||||||
|
m_angularMotorDecayTimescale = 120;
|
||||||
|
m_VhoverHeight = 0;
|
||||||
|
m_VhoverEfficiency = 1;
|
||||||
|
m_VhoverTimescale = 10;
|
||||||
|
m_VehicleBuoyancy = 0;
|
||||||
|
// m_linearDeflectionEfficiency = 1;
|
||||||
|
// m_linearDeflectionTimescale = 1;
|
||||||
|
// m_angularDeflectionEfficiency = 1;
|
||||||
|
// m_angularDeflectionTimescale = 1000;
|
||||||
|
// m_bankingEfficiency = 0;
|
||||||
|
// m_bankingMix = 1;
|
||||||
|
// m_bankingTimescale = 10;
|
||||||
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
|
m_flags &=
|
||||||
|
~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||||
|
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
||||||
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
break;
|
||||||
|
case Vehicle.TYPE_CAR:
|
||||||
|
m_linearFrictionTimescale = new Vector3(100, 2, 1000);
|
||||||
|
m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
|
||||||
|
m_linearMotorDirection = Vector3.Zero;
|
||||||
|
m_linearMotorTimescale = 1;
|
||||||
|
m_linearMotorDecayTimescale = 60;
|
||||||
|
m_angularMotorDirection = Vector3.Zero;
|
||||||
|
m_angularMotorTimescale = 1;
|
||||||
|
m_angularMotorDecayTimescale = 0.8f;
|
||||||
|
m_VhoverHeight = 0;
|
||||||
|
m_VhoverEfficiency = 0;
|
||||||
|
m_VhoverTimescale = 1000;
|
||||||
|
m_VehicleBuoyancy = 0;
|
||||||
|
// // m_linearDeflectionEfficiency = 1;
|
||||||
|
// // m_linearDeflectionTimescale = 2;
|
||||||
|
// // m_angularDeflectionEfficiency = 0;
|
||||||
|
// m_angularDeflectionTimescale = 10;
|
||||||
|
m_verticalAttractionEfficiency = 1;
|
||||||
|
m_verticalAttractionTimescale = 10;
|
||||||
|
// m_bankingEfficiency = -0.2f;
|
||||||
|
// m_bankingMix = 1;
|
||||||
|
// m_bankingTimescale = 1;
|
||||||
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
|
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||||
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY |
|
||||||
|
VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
break;
|
||||||
|
case Vehicle.TYPE_BOAT:
|
||||||
|
m_linearFrictionTimescale = new Vector3(10, 3, 2);
|
||||||
|
m_angularFrictionTimescale = new Vector3(10,10,10);
|
||||||
|
m_linearMotorDirection = Vector3.Zero;
|
||||||
|
m_linearMotorTimescale = 5;
|
||||||
|
m_linearMotorDecayTimescale = 60;
|
||||||
|
m_angularMotorDirection = Vector3.Zero;
|
||||||
|
m_angularMotorTimescale = 4;
|
||||||
|
m_angularMotorDecayTimescale = 4;
|
||||||
|
m_VhoverHeight = 0;
|
||||||
|
m_VhoverEfficiency = 0.5f;
|
||||||
|
m_VhoverTimescale = 2;
|
||||||
|
m_VehicleBuoyancy = 1;
|
||||||
|
// m_linearDeflectionEfficiency = 0.5f;
|
||||||
|
// m_linearDeflectionTimescale = 3;
|
||||||
|
// m_angularDeflectionEfficiency = 0.5f;
|
||||||
|
// m_angularDeflectionTimescale = 5;
|
||||||
|
m_verticalAttractionEfficiency = 0.5f;
|
||||||
|
m_verticalAttractionTimescale = 5;
|
||||||
|
// m_bankingEfficiency = -0.3f;
|
||||||
|
// m_bankingMix = 0.8f;
|
||||||
|
// m_bankingTimescale = 1;
|
||||||
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
|
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY |
|
||||||
|
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
||||||
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY |
|
||||||
|
VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
break;
|
||||||
|
case Vehicle.TYPE_AIRPLANE:
|
||||||
|
m_linearFrictionTimescale = new Vector3(200, 10, 5);
|
||||||
|
m_angularFrictionTimescale = new Vector3(20, 20, 20);
|
||||||
|
m_linearMotorDirection = Vector3.Zero;
|
||||||
|
m_linearMotorTimescale = 2;
|
||||||
|
m_linearMotorDecayTimescale = 60;
|
||||||
|
m_angularMotorDirection = Vector3.Zero;
|
||||||
|
m_angularMotorTimescale = 4;
|
||||||
|
m_angularMotorDecayTimescale = 4;
|
||||||
|
m_VhoverHeight = 0;
|
||||||
|
m_VhoverEfficiency = 0.5f;
|
||||||
|
m_VhoverTimescale = 1000;
|
||||||
|
m_VehicleBuoyancy = 0;
|
||||||
|
// m_linearDeflectionEfficiency = 0.5f;
|
||||||
|
// m_linearDeflectionTimescale = 3;
|
||||||
|
// m_angularDeflectionEfficiency = 1;
|
||||||
|
// m_angularDeflectionTimescale = 2;
|
||||||
|
m_verticalAttractionEfficiency = 0.9f;
|
||||||
|
m_verticalAttractionTimescale = 2;
|
||||||
|
// m_bankingEfficiency = 1;
|
||||||
|
// m_bankingMix = 0.7f;
|
||||||
|
// m_bankingTimescale = 2;
|
||||||
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
|
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||||
|
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
||||||
|
break;
|
||||||
|
case Vehicle.TYPE_BALLOON:
|
||||||
|
m_linearFrictionTimescale = new Vector3(5, 5, 5);
|
||||||
|
m_angularFrictionTimescale = new Vector3(10, 10, 10);
|
||||||
|
m_linearMotorDirection = Vector3.Zero;
|
||||||
|
m_linearMotorTimescale = 5;
|
||||||
|
m_linearMotorDecayTimescale = 60;
|
||||||
|
m_angularMotorDirection = Vector3.Zero;
|
||||||
|
m_angularMotorTimescale = 6;
|
||||||
|
m_angularMotorDecayTimescale = 10;
|
||||||
|
m_VhoverHeight = 5;
|
||||||
|
m_VhoverEfficiency = 0.8f;
|
||||||
|
m_VhoverTimescale = 10;
|
||||||
|
m_VehicleBuoyancy = 1;
|
||||||
|
// m_linearDeflectionEfficiency = 0;
|
||||||
|
// m_linearDeflectionTimescale = 5;
|
||||||
|
// m_angularDeflectionEfficiency = 0;
|
||||||
|
// m_angularDeflectionTimescale = 5;
|
||||||
|
m_verticalAttractionEfficiency = 1;
|
||||||
|
m_verticalAttractionTimescale = 1000;
|
||||||
|
// m_bankingEfficiency = 0;
|
||||||
|
// m_bankingMix = 0.7f;
|
||||||
|
// m_bankingTimescale = 5;
|
||||||
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
|
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||||
|
VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}//end SetDefaultsForType
|
||||||
|
|
||||||
|
internal void Enable(IntPtr pBody, OdeScene pParentScene)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy);
|
||||||
|
if (m_type == Vehicle.TYPE_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_body = pBody;
|
||||||
|
//KF: This used to set up the linear and angular joints
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Step(float pTimestep, OdeScene pParentScene)
|
||||||
|
{
|
||||||
|
if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE)
|
||||||
|
return;
|
||||||
|
frcount++; // used to limit debug comment output
|
||||||
|
if (frcount > 100)
|
||||||
|
frcount = 0;
|
||||||
|
|
||||||
|
MoveLinear(pTimestep, pParentScene);
|
||||||
|
MoveAngular(pTimestep);
|
||||||
|
}// end Step
|
||||||
|
|
||||||
|
private void MoveLinear(float pTimestep, OdeScene _pParentScene)
|
||||||
|
{
|
||||||
|
if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
|
||||||
|
{
|
||||||
|
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
|
||||||
|
|
||||||
|
// add drive to body
|
||||||
|
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
|
||||||
|
m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
|
||||||
|
|
||||||
|
// This will work temporarily, but we really need to compare speed on an axis
|
||||||
|
// KF: Limit body velocity to applied velocity?
|
||||||
|
if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
|
||||||
|
m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
|
||||||
|
if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
|
||||||
|
m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
|
||||||
|
if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
|
||||||
|
m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
|
||||||
|
|
||||||
|
// decay applied velocity
|
||||||
|
Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
|
||||||
|
//Console.WriteLine("decay: " + decayfraction);
|
||||||
|
m_linearMotorDirection -= m_linearMotorDirection * decayfraction;
|
||||||
|
//Console.WriteLine("actual: " + m_linearMotorDirection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // requested is not significant
|
||||||
|
// if what remains of applied is small, zero it.
|
||||||
|
if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
|
||||||
|
m_lastLinearVelocityVector = Vector3.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// convert requested object velocity to world-referenced vector
|
||||||
|
m_dir = m_lastLinearVelocityVector;
|
||||||
|
d.Quaternion rot = d.BodyGetQuaternion(Body);
|
||||||
|
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
|
||||||
|
m_dir *= rotq; // apply obj rotation to velocity vector
|
||||||
|
|
||||||
|
// add Gravity andBuoyancy
|
||||||
|
// KF: So far I have found no good method to combine a script-requested
|
||||||
|
// .Z velocity and gravity. Therefore only 0g will used script-requested
|
||||||
|
// .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
|
||||||
|
Vector3 grav = Vector3.Zero;
|
||||||
|
if(m_VehicleBuoyancy < 1.0f)
|
||||||
|
{
|
||||||
|
// There is some gravity, make a gravity force vector
|
||||||
|
// that is applied after object velocity.
|
||||||
|
d.Mass objMass;
|
||||||
|
d.BodyGetMass(Body, out objMass);
|
||||||
|
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
||||||
|
grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy);
|
||||||
|
// Preserve the current Z velocity
|
||||||
|
d.Vector3 vel_now = d.BodyGetLinearVel(Body);
|
||||||
|
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
|
||||||
|
} // else its 1.0, no gravity.
|
||||||
|
|
||||||
|
// Check if hovering
|
||||||
|
if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
|
||||||
|
{
|
||||||
|
// We should hover, get the target height
|
||||||
|
d.Vector3 pos = d.BodyGetPosition(Body);
|
||||||
|
if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY)
|
||||||
|
{
|
||||||
|
m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
|
||||||
|
}
|
||||||
|
else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY)
|
||||||
|
{
|
||||||
|
m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||||
|
}
|
||||||
|
else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT)
|
||||||
|
{
|
||||||
|
m_VhoverTargetHeight = m_VhoverHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY)
|
||||||
|
{
|
||||||
|
// If body is aready heigher, use its height as target height
|
||||||
|
if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
|
||||||
|
// m_VhoverTimescale = 0f; // time to acheive height
|
||||||
|
// pTimestep is time since last frame,in secs
|
||||||
|
float herr0 = pos.Z - m_VhoverTargetHeight;
|
||||||
|
//if(frcount == 0) Console.WriteLine("herr0=" + herr0);
|
||||||
|
// Replace Vertical speed with correction figure if significant
|
||||||
|
if(Math.Abs(herr0) > 0.01f )
|
||||||
|
{
|
||||||
|
d.Mass objMass;
|
||||||
|
d.BodyGetMass(Body, out objMass);
|
||||||
|
m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
|
||||||
|
// m_VhoverEfficiency is not yet implemented
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dir.Z = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply velocity
|
||||||
|
d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z);
|
||||||
|
//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z);
|
||||||
|
// apply gravity force
|
||||||
|
d.BodyAddForce(Body, grav.X, grav.Y, grav.Z);
|
||||||
|
//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z);
|
||||||
|
|
||||||
|
|
||||||
|
// apply friction
|
||||||
|
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
|
||||||
|
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
|
||||||
|
} // end MoveLinear()
|
||||||
|
|
||||||
|
private void MoveAngular(float pTimestep)
|
||||||
|
{
|
||||||
|
|
||||||
|
// m_angularMotorDirection is the latest value from the script, and is decayed here
|
||||||
|
// m_angularMotorDirectionLASTSET is the latest value from the script
|
||||||
|
// m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here
|
||||||
|
|
||||||
|
if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
|
||||||
|
{
|
||||||
|
if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body);
|
||||||
|
// ramp up to new value
|
||||||
|
Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep);
|
||||||
|
m_lastAngularVelocityVector += (addAmount * 10f);
|
||||||
|
//if(frcount == 0) Console.WriteLine("add: " + addAmount);
|
||||||
|
|
||||||
|
// limit applied value to what was set by script
|
||||||
|
// This will work temporarily, but we really need to compare speed on an axis
|
||||||
|
if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X))
|
||||||
|
m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X;
|
||||||
|
if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y))
|
||||||
|
m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y;
|
||||||
|
if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z))
|
||||||
|
m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z;
|
||||||
|
|
||||||
|
// decay the requested value
|
||||||
|
Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep)));
|
||||||
|
//Console.WriteLine("decay: " + decayfraction);
|
||||||
|
m_angularMotorDirection -= m_angularMotorDirection * decayfraction;
|
||||||
|
//Console.WriteLine("actual: " + m_linearMotorDirection);
|
||||||
|
}
|
||||||
|
// KF: m_lastAngularVelocityVector is rotational speed in rad/sec ?
|
||||||
|
|
||||||
|
// Vertical attractor section
|
||||||
|
|
||||||
|
// d.Mass objMass;
|
||||||
|
// d.BodyGetMass(Body, out objMass);
|
||||||
|
// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
|
||||||
|
float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep);
|
||||||
|
// get present body rotation
|
||||||
|
d.Quaternion rot = d.BodyGetQuaternion(Body);
|
||||||
|
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
|
||||||
|
// make a vector pointing up
|
||||||
|
Vector3 verterr = Vector3.Zero;
|
||||||
|
verterr.Z = 1.0f;
|
||||||
|
// rotate it to Body Angle
|
||||||
|
verterr = verterr * rotq;
|
||||||
|
// verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
|
||||||
|
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
|
||||||
|
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
|
||||||
|
if (verterr.Z < 0.0f)
|
||||||
|
{
|
||||||
|
verterr.X = 2.0f - verterr.X;
|
||||||
|
verterr.Y = 2.0f - verterr.Y;
|
||||||
|
}
|
||||||
|
// Error is 0 (no error) to +/- 2 (max error)
|
||||||
|
// scale it by servo
|
||||||
|
verterr = verterr * servo;
|
||||||
|
|
||||||
|
// rotate to object frame
|
||||||
|
// verterr = verterr * rotq;
|
||||||
|
|
||||||
|
// As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
|
||||||
|
// Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
|
||||||
|
m_lastAngularVelocityVector.X += verterr.Y;
|
||||||
|
m_lastAngularVelocityVector.Y -= verterr.X;
|
||||||
|
/*
|
||||||
|
if(frcount == 0)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector);
|
||||||
|
Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}",
|
||||||
|
Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z);
|
||||||
|
// apply friction
|
||||||
|
Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
|
||||||
|
m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount;
|
||||||
|
|
||||||
|
} //end MoveAngular
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,443 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSimulator 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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OdeAPI;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Processes raycast requests as ODE is in a state to be able to do them.
|
||||||
|
/// This ensures that it's thread safe and there will be no conflicts.
|
||||||
|
/// Requests get returned by a different thread then they were requested by.
|
||||||
|
/// </summary>
|
||||||
|
public class ODERayCastRequestManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pending ray requests
|
||||||
|
/// </summary>
|
||||||
|
protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scene that created this object.
|
||||||
|
/// </summary>
|
||||||
|
private OdeScene m_scene;
|
||||||
|
|
||||||
|
IntPtr ray;
|
||||||
|
|
||||||
|
private const int ColisionContactGeomsPerTest = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ODE near callback delegate
|
||||||
|
/// </summary>
|
||||||
|
private d.NearCallback nearCallback;
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private List<ContactResult> m_contactResults = new List<ContactResult>();
|
||||||
|
|
||||||
|
public ODERayCastRequestManager(OdeScene pScene)
|
||||||
|
{
|
||||||
|
m_scene = pScene;
|
||||||
|
nearCallback = near;
|
||||||
|
ray = d.CreateRay(IntPtr.Zero, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues a raycast
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Origin of Ray</param>
|
||||||
|
/// <param name="direction">Ray normal</param>
|
||||||
|
/// <param name="length">Ray length</param>
|
||||||
|
/// <param name="retMethod">Return method to send the results</param>
|
||||||
|
public void QueueRequest(Vector3 position, Vector3 direction, float length, RayCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = IntPtr.Zero;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.Count = 0;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RayCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = geom;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = 0;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = IntPtr.Zero;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.Count = 0;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = geom;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = 0;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues a raycast
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Origin of Ray</param>
|
||||||
|
/// <param name="direction">Ray normal</param>
|
||||||
|
/// <param name="length">Ray length</param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <param name="retMethod">Return method to send the results</param>
|
||||||
|
public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = IntPtr.Zero;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = count;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = geom;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = count;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = IntPtr.Zero;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = count;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueRequest(IntPtr geom, Vector3 position, Vector3 direction, float length, int count, RaycastCallback retMethod)
|
||||||
|
{
|
||||||
|
ODERayRequest req = new ODERayRequest();
|
||||||
|
req.geom = geom;
|
||||||
|
req.callbackMethod = retMethod;
|
||||||
|
req.length = length;
|
||||||
|
req.Normal = direction;
|
||||||
|
req.Origin = position;
|
||||||
|
req.Count = count;
|
||||||
|
|
||||||
|
m_PendingRequests.Enqueue(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process all queued raycast requests
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Time in MS the raycasts took to process.</returns>
|
||||||
|
public int ProcessQueuedRequests()
|
||||||
|
{
|
||||||
|
int time = System.Environment.TickCount;
|
||||||
|
|
||||||
|
if (m_PendingRequests.Count <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (m_scene.ContactgeomsArray == IntPtr.Zero) // oops something got wrong or scene isn't ready still
|
||||||
|
{
|
||||||
|
m_PendingRequests.Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ODERayRequest req;
|
||||||
|
|
||||||
|
int i = 50; // arbitary limit of processed tests per frame
|
||||||
|
|
||||||
|
while(m_PendingRequests.Dequeue(out req))
|
||||||
|
{
|
||||||
|
if (req.geom == IntPtr.Zero)
|
||||||
|
doSpaceRay(req);
|
||||||
|
else
|
||||||
|
doGeomRay(req);
|
||||||
|
if(--i < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_contactResults)
|
||||||
|
m_contactResults.Clear();
|
||||||
|
|
||||||
|
return System.Environment.TickCount - time;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Method that actually initiates the raycast with full top space
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="req"></param>
|
||||||
|
private void doSpaceRay(ODERayRequest req)
|
||||||
|
{
|
||||||
|
// Create the ray
|
||||||
|
// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
|
||||||
|
d.GeomRaySetLength(ray, req.length);
|
||||||
|
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
|
||||||
|
|
||||||
|
// Collide test
|
||||||
|
d.SpaceCollide2(m_scene.TopSpace, ray, IntPtr.Zero, nearCallback);
|
||||||
|
|
||||||
|
// Remove Ray
|
||||||
|
// d.GeomDestroy(ray);
|
||||||
|
|
||||||
|
if (req.callbackMethod == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (req.callbackMethod is RaycastCallback)
|
||||||
|
{
|
||||||
|
// Define default results
|
||||||
|
bool hitYN = false;
|
||||||
|
uint hitConsumerID = 0;
|
||||||
|
float distance = 999999999999f;
|
||||||
|
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
|
||||||
|
Vector3 snormal = Vector3.Zero;
|
||||||
|
|
||||||
|
// Find closest contact and object.
|
||||||
|
lock (m_contactResults)
|
||||||
|
{
|
||||||
|
foreach (ContactResult cResult in m_contactResults)
|
||||||
|
{
|
||||||
|
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
|
||||||
|
{
|
||||||
|
closestcontact = cResult.Pos;
|
||||||
|
hitConsumerID = cResult.ConsumerID;
|
||||||
|
distance = cResult.Depth;
|
||||||
|
hitYN = true;
|
||||||
|
snormal = cResult.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_contactResults.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((RayCallback)req.callbackMethod)(m_contactResults);
|
||||||
|
lock (m_PendingRequests)
|
||||||
|
m_contactResults.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method that actually initiates the raycast with a geom
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="req"></param>
|
||||||
|
private void doGeomRay(ODERayRequest req)
|
||||||
|
{
|
||||||
|
// Create the ray
|
||||||
|
// IntPtr ray = d.CreateRay(m_scene.TopSpace, req.length);
|
||||||
|
d.GeomRaySetLength(ray, req.length);
|
||||||
|
d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
|
||||||
|
|
||||||
|
// Collide test
|
||||||
|
d.SpaceCollide2(req.geom, ray, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
|
||||||
|
|
||||||
|
// Remove Ray
|
||||||
|
// d.GeomDestroy(ray);
|
||||||
|
|
||||||
|
if (req.callbackMethod == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (req.callbackMethod is RaycastCallback)
|
||||||
|
{
|
||||||
|
// Define default results
|
||||||
|
bool hitYN = false;
|
||||||
|
uint hitConsumerID = 0;
|
||||||
|
float distance = 999999999999f;
|
||||||
|
Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f);
|
||||||
|
Vector3 snormal = Vector3.Zero;
|
||||||
|
|
||||||
|
// Find closest contact and object.
|
||||||
|
lock (m_contactResults)
|
||||||
|
{
|
||||||
|
foreach (ContactResult cResult in m_contactResults)
|
||||||
|
{
|
||||||
|
if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact))
|
||||||
|
{
|
||||||
|
closestcontact = cResult.Pos;
|
||||||
|
hitConsumerID = cResult.ConsumerID;
|
||||||
|
distance = cResult.Depth;
|
||||||
|
hitYN = true;
|
||||||
|
snormal = cResult.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_contactResults.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((RayCallback)req.callbackMethod)(m_contactResults);
|
||||||
|
lock (m_PendingRequests)
|
||||||
|
m_contactResults.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
|
||||||
|
{
|
||||||
|
IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
|
||||||
|
if (ContactgeomsArray == IntPtr.Zero || index >= ColisionContactGeomsPerTest)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
|
||||||
|
newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the standard Near. g2 is the ray
|
||||||
|
private void near(IntPtr space, IntPtr g1, IntPtr g2)
|
||||||
|
{
|
||||||
|
//Don't test against heightfield Geom, or you'll be sorry!
|
||||||
|
// Exclude heightfield geom
|
||||||
|
|
||||||
|
if (g1 == IntPtr.Zero || g1 == g2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms.
|
||||||
|
if (d.GeomIsSpace(g1))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
count = d.CollidePtr(g1, g2, ColisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
|
||||||
|
}
|
||||||
|
catch (SEHException)
|
||||||
|
{
|
||||||
|
m_log.Error("[PHYSICS Ray]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PhysicsActor p1 = null;
|
||||||
|
|
||||||
|
if (g1 != IntPtr.Zero)
|
||||||
|
m_scene.actor_name_map.TryGetValue(g1, out p1);
|
||||||
|
|
||||||
|
d.ContactGeom curcontact = new d.ContactGeom();
|
||||||
|
// Loop over contacts, build results.
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (!GetCurContactGeom(i, ref curcontact))
|
||||||
|
break;
|
||||||
|
if (p1 != null) {
|
||||||
|
if (p1 is OdePrim)
|
||||||
|
{
|
||||||
|
ContactResult collisionresult = new ContactResult();
|
||||||
|
|
||||||
|
collisionresult.ConsumerID = ((OdePrim)p1).m_localID;
|
||||||
|
collisionresult.Pos = new Vector3(curcontact.pos.X, curcontact.pos.Y, curcontact.pos.Z);
|
||||||
|
collisionresult.Depth = curcontact.depth;
|
||||||
|
collisionresult.Normal = new Vector3(curcontact.normal.X, curcontact.normal.Y,
|
||||||
|
curcontact.normal.Z);
|
||||||
|
lock (m_contactResults)
|
||||||
|
m_contactResults.Add(collisionresult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dereference the creator scene so that it can be garbage collected if needed.
|
||||||
|
/// </summary>
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ODERayRequest
|
||||||
|
{
|
||||||
|
public IntPtr geom;
|
||||||
|
public Vector3 Origin;
|
||||||
|
public Vector3 Normal;
|
||||||
|
public int Count;
|
||||||
|
public float length;
|
||||||
|
public object callbackMethod;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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 OpenSimulator 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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OdeAPI;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ODE plugin
|
||||||
|
/// </summary>
|
||||||
|
public class OdePlugin : IPhysicsPlugin
|
||||||
|
{
|
||||||
|
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private OdeScene m_scene;
|
||||||
|
|
||||||
|
public bool Init()
|
||||||
|
{
|
||||||
|
if (d.InitODE2(0) != 0)
|
||||||
|
{
|
||||||
|
if (d.AllocateODEDataForThread(~0U) == 0)
|
||||||
|
{
|
||||||
|
d.CloseODE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhysicsScene GetScene(String sceneIdentifier)
|
||||||
|
{
|
||||||
|
if (m_scene == null)
|
||||||
|
{
|
||||||
|
m_scene = new OdeScene(sceneIdentifier);
|
||||||
|
}
|
||||||
|
return (m_scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName()
|
||||||
|
{
|
||||||
|
return ("UbitODE");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
d.CloseODE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright ODE
|
||||||
|
* Ode.NET - .NET bindings for ODE
|
||||||
|
* Jason Perkins (starkos@industriousone.com)
|
||||||
|
* Licensed under the New BSD
|
||||||
|
* Part of the OpenDynamicsEngine
|
||||||
|
Open Dynamics Engine
|
||||||
|
Copyright (c) 2001-2007, Russell L. Smith.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
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 names of ODE's copyright owner 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"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 COPYRIGHT
|
||||||
|
OWNER OR 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.Runtime.InteropServices;
|
||||||
|
using OdeAPI;
|
||||||
|
|
||||||
|
namespace ODEDrawstuff
|
||||||
|
{
|
||||||
|
/*#if dDOUBLE
|
||||||
|
using dReal = System.Double;
|
||||||
|
#else
|
||||||
|
*/
|
||||||
|
using dReal = System.Single;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
public static class ds
|
||||||
|
{
|
||||||
|
public const int VERSION = 2;
|
||||||
|
|
||||||
|
public enum Texture
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Wood
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate void CallbackFunction(int arg);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct Functions
|
||||||
|
{
|
||||||
|
public int version;
|
||||||
|
public CallbackFunction start;
|
||||||
|
public CallbackFunction step;
|
||||||
|
public CallbackFunction command;
|
||||||
|
public CallbackFunction stop;
|
||||||
|
public string path_to_textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsDrawBox")]
|
||||||
|
public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsDrawCapsule")]
|
||||||
|
public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsDrawConvex")]
|
||||||
|
public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsSetColor")]
|
||||||
|
public static extern void SetColor(float red, float green, float blue);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsSetTexture")]
|
||||||
|
public static extern void SetTexture(Texture texture);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsSetViewpoint")]
|
||||||
|
public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
|
||||||
|
|
||||||
|
[DllImport("drawstuff", EntryPoint = "dsSimulationLoop")]
|
||||||
|
public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue