aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorMelanie Thielker2014-10-03 18:27:27 +0200
committerMelanie Thielker2014-10-03 18:27:27 +0200
commit93fa3777d2de7d5d17039ee18014c9d73e13cbc5 (patch)
treea54caa4ae0003025024918088c1c88094c219663 /OpenSim/Region/Physics
parentAlso store names of assets in the AnimationSet (diff)
parentclean up coments, use a even faster XY move request detection (diff)
downloadopensim-SC_OLD-93fa3777d2de7d5d17039ee18014c9d73e13cbc5.zip
opensim-SC_OLD-93fa3777d2de7d5d17039ee18014c9d73e13cbc5.tar.gz
opensim-SC_OLD-93fa3777d2de7d5d17039ee18014c9d73e13cbc5.tar.bz2
opensim-SC_OLD-93fa3777d2de7d5d17039ee18014c9d73e13cbc5.tar.xz
Merge branch 'ubitworkmaster'
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs211
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs167
2 files changed, 321 insertions, 57 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index daf6c7c..992fae7 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -79,6 +79,7 @@ namespace OpenSim.Region.Physics.OdePlugin
79 private Vector3 _acceleration; 79 private Vector3 _acceleration;
80 private Vector3 m_rotationalVelocity; 80 private Vector3 m_rotationalVelocity;
81 private Vector3 m_size; 81 private Vector3 m_size;
82 private Vector3 m_collideNormal;
82 private Quaternion m_orientation; 83 private Quaternion m_orientation;
83 private Quaternion m_orientation2D; 84 private Quaternion m_orientation2D;
84 private float m_mass = 80f; 85 private float m_mass = 80f;
@@ -109,6 +110,7 @@ namespace OpenSim.Region.Physics.OdePlugin
109 110
110 private bool _zeroFlag = false; 111 private bool _zeroFlag = false;
111 112
113
112 private uint m_localID = 0; 114 private uint m_localID = 0;
113 public bool m_returnCollisions = false; 115 public bool m_returnCollisions = false;
114 // taints and their non-tainted counterparts 116 // taints and their non-tainted counterparts
@@ -153,9 +155,7 @@ namespace OpenSim.Region.Physics.OdePlugin
153 public UUID m_uuid; 155 public UUID m_uuid;
154 public bool bad = false; 156 public bool bad = false;
155 157
156 float mu; 158 float mu;
157
158
159 159
160 public OdeCharacter(uint localID, String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor) 160 public OdeCharacter(uint localID, String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
161 { 161 {
@@ -864,11 +864,12 @@ namespace OpenSim.Region.Physics.OdePlugin
864 x = tx * cos - y * sin; 864 x = tx * cos - y * sin;
865 y = tx * sin + y * cos; 865 y = tx * sin + y * cos;
866 } 866 }
867 867
868 868 public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
869 public bool Collide(IntPtr me,IntPtr other, bool reverse, ref d.ContactGeom contact, ref bool feetcollision) 869 ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
870 { 870 {
871 feetcollision = false; 871 feetcollision = false;
872 useAltcontact = false;
872 873
873 if (me == capsule) 874 if (me == capsule)
874 { 875 {
@@ -899,31 +900,78 @@ namespace OpenSim.Region.Physics.OdePlugin
899 { 900 {
900 feetcollision = true; 901 feetcollision = true;
901 if (h < boneOff) 902 if (h < boneOff)
903 {
904 m_collideNormal.X = contact.normal.X;
905 m_collideNormal.Y = contact.normal.Y;
906 m_collideNormal.Z = contact.normal.Z;
902 IsColliding = true; 907 IsColliding = true;
908 }
903 } 909 }
904 return true; 910 return true;
905 } 911 }
912/*
913 d.AABB aabb;
914 d.GeomGetAABB(other,out aabb);
915 float othertop = aabb.MaxZ - _position.Z;
916*/
917// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
918 if (offset.Z > 0 || contact.normal.Z > 0.35f)
919 {
920 if (offset.Z <= 0)
921 {
922 feetcollision = true;
923 if (h < boneOff)
924 {
925 m_collideNormal.X = contact.normal.X;
926 m_collideNormal.Y = contact.normal.Y;
927 m_collideNormal.Z = contact.normal.Z;
928 IsColliding = true;
929 }
930 }
906 931
907 if (offset.Z > 0) 932 if (contact.normal.Z < 0.2f)
933 {
934 contact.normal.Z = 0;
935 float t = contact.normal.X * contact.normal.X + contact.normal.Y * contact.normal.Y;
936 if (t > 0)
937 {
938 t = 1.0f / t;
939 contact.normal.X *= t;
940 contact.normal.Y *= t;
941 }
942 }
908 return true; 943 return true;
944 }
945
946 altContact = contact;
947 useAltcontact = true;
909 948
910 offset.Normalize(); 949 offset.Normalize();
911 950
951 if (contact.depth > 0.1f)
952 contact.depth = 0.1f;
953
912 if (reverse) 954 if (reverse)
913 { 955 {
914 contact.normal.X = offset.X; 956 altContact.normal.X = offset.X;
915 contact.normal.Y = offset.Y; 957 altContact.normal.Y = offset.Y;
916 contact.normal.Z = offset.Z; 958 altContact.normal.Z = offset.Z;
917 } 959 }
918 else 960 else
919 { 961 {
920 contact.normal.X = -offset.X; 962 altContact.normal.X = -offset.X;
921 contact.normal.Y = -offset.Y; 963 altContact.normal.Y = -offset.Y;
922 contact.normal.Z = -offset.Z; 964 altContact.normal.Z = -offset.Z;
923 } 965 }
966
924 feetcollision = true; 967 feetcollision = true;
925 if (h < boneOff) 968 if (h < boneOff)
969 {
970 m_collideNormal.X = contact.normal.X;
971 m_collideNormal.Y = contact.normal.Y;
972 m_collideNormal.Z = contact.normal.Z;
926 IsColliding = true; 973 IsColliding = true;
974 }
927 return true; 975 return true;
928 } 976 }
929 return false; 977 return false;
@@ -1003,6 +1051,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1003 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z); 1051 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1004 float velLengthSquared = vel.LengthSquared(); 1052 float velLengthSquared = vel.LengthSquared();
1005 1053
1054
1055 Vector3 ctz = _target_velocity;
1056
1006 float movementdivisor = 1f; 1057 float movementdivisor = 1f;
1007 //Ubit change divisions into multiplications below 1058 //Ubit change divisions into multiplications below
1008 if (!m_alwaysRun) 1059 if (!m_alwaysRun)
@@ -1010,13 +1061,16 @@ namespace OpenSim.Region.Physics.OdePlugin
1010 else 1061 else
1011 movementdivisor = 1 / runDivisor; 1062 movementdivisor = 1 / runDivisor;
1012 1063
1064 ctz.X *= movementdivisor;
1065 ctz.Y *= movementdivisor;
1066
1013 //****************************************** 1067 //******************************************
1014 // colide with land 1068 // colide with land
1015 1069
1016 d.AABB aabb; 1070 d.AABB aabb;
1017// d.GeomGetAABB(feetbox, out aabb); 1071// d.GeomGetAABB(feetbox, out aabb);
1018 d.GeomGetAABB(capsule, out aabb); 1072 d.GeomGetAABB(capsule, out aabb);
1019 float chrminZ = aabb.MinZ; ; // move up a bit 1073 float chrminZ = aabb.MinZ; // move up a bit
1020 Vector3 posch = localpos; 1074 Vector3 posch = localpos;
1021 1075
1022 float ftmp; 1076 float ftmp;
@@ -1031,15 +1085,18 @@ namespace OpenSim.Region.Physics.OdePlugin
1031 float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y); 1085 float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
1032 if (chrminZ < terrainheight) 1086 if (chrminZ < terrainheight)
1033 { 1087 {
1088 if (ctz.Z < 0)
1089 ctz.Z = 0;
1090
1091 Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
1034 float depth = terrainheight - chrminZ; 1092 float depth = terrainheight - chrminZ;
1093
1094 vec.Z = depth * PID_P * 50;
1095
1035 if (!flying) 1096 if (!flying)
1036 { 1097 vec.Z += -vel.Z * PID_D;
1037 vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 50;
1038 }
1039 else
1040 vec.Z = depth * PID_P * 50;
1041 1098
1042 if (depth < 0.1f) 1099 if (depth < 0.2f)
1043 { 1100 {
1044 m_colliderGroundfilter++; 1101 m_colliderGroundfilter++;
1045 if (m_colliderGroundfilter > 2) 1102 if (m_colliderGroundfilter > 2)
@@ -1053,50 +1110,83 @@ namespace OpenSim.Region.Physics.OdePlugin
1053 m_freemove = false; 1110 m_freemove = false;
1054 } 1111 }
1055 1112
1113 m_collideNormal.X = n.X;
1114 m_collideNormal.Y = n.Y;
1115 m_collideNormal.Z = n.Z;
1116
1056 m_iscollidingGround = true; 1117 m_iscollidingGround = true;
1057 1118
1119
1058 ContactPoint contact = new ContactPoint(); 1120 ContactPoint contact = new ContactPoint();
1059 contact.PenetrationDepth = depth; 1121 contact.PenetrationDepth = depth;
1060 contact.Position.X = localpos.X; 1122 contact.Position.X = localpos.X;
1061 contact.Position.Y = localpos.Y; 1123 contact.Position.Y = localpos.Y;
1062 contact.Position.Z = terrainheight; 1124 contact.Position.Z = terrainheight;
1063 contact.SurfaceNormal.X = 0.0f; 1125 contact.SurfaceNormal.X = -n.X;
1064 contact.SurfaceNormal.Y = 0.0f; 1126 contact.SurfaceNormal.Y = -n.Y;
1065 contact.SurfaceNormal.Z = -1f; 1127 contact.SurfaceNormal.Z = -n.Z;
1066 contact.RelativeSpeed = -vel.Z; 1128 contact.RelativeSpeed = -vel.Z;
1067 contact.CharacterFeet = true; 1129 contact.CharacterFeet = true;
1068 AddCollisionEvent(0, contact); 1130 AddCollisionEvent(0, contact);
1069 1131
1070 vec.Z *= 0.5f; 1132// vec.Z *= 0.5f;
1071 } 1133 }
1072 } 1134 }
1073 1135
1074 else 1136 else
1075 { 1137 {
1076 m_colliderGroundfilter = 0; 1138 m_colliderGroundfilter -= 5;
1077 m_iscollidingGround = false; 1139 if (m_colliderGroundfilter <= 0)
1140 {
1141 m_colliderGroundfilter = 0;
1142 m_iscollidingGround = false;
1143 }
1078 } 1144 }
1079 } 1145 }
1080 else 1146 else
1081 { 1147 {
1082 m_colliderGroundfilter = 0; 1148 m_colliderGroundfilter -= 5;
1083 m_iscollidingGround = false; 1149 if (m_colliderGroundfilter <= 0)
1150 {
1151 m_colliderGroundfilter = 0;
1152 m_iscollidingGround = false;
1153 }
1084 } 1154 }
1085 1155
1086 1156
1087 //****************************************** 1157 //******************************************
1158 if (!m_iscolliding)
1159 m_collideNormal.Z = 0;
1160
1161 bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
1162
1088 1163
1089 bool tviszero = (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f);
1090 1164
1091 // if (!tviszero || m_iscolliding || velLengthSquared <0.01)
1092 if (!tviszero) 1165 if (!tviszero)
1166 {
1093 m_freemove = false; 1167 m_freemove = false;
1094 1168
1169 // movement relative to surface if moving on it
1170 // dont disturbe vertical movement, ie jumps
1171 if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
1172 {
1173 float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
1174 ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
1175 ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
1176 ctz.Z -= p;
1177 if (ctz.Z < 0)
1178 ctz.Z *= 2;
1179
1180 }
1181
1182 }
1183
1184
1095 if (!m_freemove) 1185 if (!m_freemove)
1096 { 1186 {
1097 1187
1098 // if velocity is zero, use position control; otherwise, velocity control 1188 // if velocity is zero, use position control; otherwise, velocity control
1099 if (tviszero && m_iscolliding) 1189 if (tviszero && m_iscolliding && !flying)
1100 { 1190 {
1101 // keep track of where we stopped. No more slippin' & slidin' 1191 // keep track of where we stopped. No more slippin' & slidin'
1102 if (!_zeroFlag) 1192 if (!_zeroFlag)
@@ -1129,22 +1219,48 @@ namespace OpenSim.Region.Physics.OdePlugin
1129 { 1219 {
1130 if (!flying) 1220 if (!flying)
1131 { 1221 {
1132 if (_target_velocity.Z > 0.0f) 1222 // we are on a surface
1223 if (ctz.Z > 0f)
1133 { 1224 {
1134 // We're colliding with something and we're not flying but we're moving 1225 // moving up or JUMPING
1135 // This means we're walking or running. JUMPING 1226 vec.Z += (ctz.Z - vel.Z) * PID_D * 1.2f;// +(_zeroPosition.Z - localpos.Z) * PID_P;
1136 vec.Z += (_target_velocity.Z - vel.Z) * PID_D * 1.2f;// +(_zeroPosition.Z - localpos.Z) * PID_P; 1227 vec.X += (ctz.X - vel.X) * (PID_D);
1228 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1137 } 1229 }
1230 else
1231 {
1232 // we are moving down on a surface
1233 if (ctz.Z == 0)
1234 {
1235 if (vel.Z > 0)
1236 vec.Z -= vel.Z * PID_D * 2.0f;
1237 vec.X += (ctz.X - vel.X) * (PID_D);
1238 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1239 }
1240 // intencionally going down
1241 else
1242 {
1243 if (ctz.Z < vel.Z)
1244 vec.Z += (ctz.Z - vel.Z) * PID_D * 2.0f;
1245 else
1246 {
1247 }
1248
1249 if (Math.Abs(ctz.X) > Math.Abs(vel.X))
1250 vec.X += (ctz.X - vel.X) * (PID_D);
1251 if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
1252 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1253 }
1254 }
1255
1138 // We're standing on something 1256 // We're standing on something
1139 vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D);
1140 vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D);
1141 } 1257 }
1142 else 1258 else
1143 { 1259 {
1144 // We're flying and colliding with something 1260 // We're flying and colliding with something
1145 vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D * 0.0625f); 1261 vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
1146 vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D * 0.0625f); 1262 vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
1147 vec.Z += (_target_velocity.Z - vel.Z) * (PID_D); 1263 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1148 } 1264 }
1149 } 1265 }
1150 else // ie not colliding 1266 else // ie not colliding
@@ -1152,9 +1268,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1152 if (flying) //(!m_iscolliding && flying) 1268 if (flying) //(!m_iscolliding && flying)
1153 { 1269 {
1154 // we're in mid air suspended 1270 // we're in mid air suspended
1155 vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D * 1.667f); 1271 vec.X += (ctz.X - vel.X) * (PID_D * 1.667f);
1156 vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D * 1.667f); 1272 vec.Y += (ctz.Y - vel.Y) * (PID_D * 1.667f);
1157 vec.Z += (_target_velocity.Z - vel.Z) * (PID_D); 1273 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1158 } 1274 }
1159 1275
1160 else 1276 else
@@ -1163,8 +1279,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1163 // m_iscolliding includes collisions with the ground. 1279 // m_iscolliding includes collisions with the ground.
1164 1280
1165 // d.Vector3 pos = d.BodyGetPosition(Body); 1281 // d.Vector3 pos = d.BodyGetPosition(Body);
1166 vec.X = (_target_velocity.X - vel.X) * PID_D * 0.833f; 1282 vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
1167 vec.Y = (_target_velocity.Y - vel.Y) * PID_D * 0.833f; 1283 vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
1284 // hack for breaking on fall
1285 if (ctz.Z == -9999f)
1286 vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass;
1168 } 1287 }
1169 } 1288 }
1170 } 1289 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 9bf2abe..2adbe01 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -935,18 +935,22 @@ namespace OpenSim.Region.Physics.OdePlugin
935 SharedTmpcontact.surface.mu = mu; 935 SharedTmpcontact.surface.mu = mu;
936 SharedTmpcontact.surface.bounce = bounce; 936 SharedTmpcontact.surface.bounce = bounce;
937 937
938 d.ContactGeom altContact = new d.ContactGeom();
939 bool useAltcontact = false;
940 bool noskip = true;
941
938 while (true) 942 while (true)
939 { 943 {
940// if (!(IgnoreNegSides && curContact.side1 < 0)) 944// if (!(IgnoreNegSides && curContact.side1 < 0))
941 { 945 {
942 bool noskip = true; 946 noskip = true;
947 useAltcontact = false;
948
943 if (dop1ava) 949 if (dop1ava)
944 { 950 {
945 if (!(((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref FeetCollision))) 951 if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
946 noskip = false;
947 else
948 { 952 {
949 if(p2.PhysicsActorType == (int)ActorTypes.Agent) 953 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
950 { 954 {
951 p1.CollidingObj = true; 955 p1.CollidingObj = true;
952 p2.CollidingObj = true; 956 p2.CollidingObj = true;
@@ -954,18 +958,32 @@ namespace OpenSim.Region.Physics.OdePlugin
954 else if (p2.Velocity.LengthSquared() > 0.0f) 958 else if (p2.Velocity.LengthSquared() > 0.0f)
955 p2.CollidingObj = true; 959 p2.CollidingObj = true;
956 } 960 }
961 else
962 noskip = false;
957 } 963 }
958 else if (dop2ava) 964 else if (dop2ava)
959 { 965 {
960 if (!(((OdeCharacter)p2).Collide(g2,g1, true, ref curContact, ref FeetCollision))) 966 if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
967 {
968 if (p1.PhysicsActorType == (int)ActorTypes.Agent)
969 {
970 p1.CollidingObj = true;
971 p2.CollidingObj = true;
972 }
973 else if (p2.Velocity.LengthSquared() > 0.0f)
974 p1.CollidingObj = true;
975 }
976 else
961 noskip = false; 977 noskip = false;
962 else if (p1.Velocity.LengthSquared() > 0.0f)
963 p1.CollidingObj = true;
964 } 978 }
965 979
966 if (noskip) 980 if (noskip)
967 { 981 {
968 Joint = CreateContacJoint(ref curContact); 982 if(useAltcontact)
983 Joint = CreateContacJoint(ref altContact);
984 else
985 Joint = CreateContacJoint(ref curContact);
986
969 if (Joint == IntPtr.Zero) 987 if (Joint == IntPtr.Zero)
970 break; 988 break;
971 989
@@ -1924,12 +1942,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1924 dy = 0; 1942 dy = 0;
1925 } 1943 }
1926 } 1944 }
1927
1928 else 1945 else
1929 { 1946 {
1930 // we still have square fixed size regions 1947 // we still have square fixed size regions
1931 // also flip x and y because of how map is done for ODE fliped axis 1948 // also flip x and y because of how map is done for ODE fliped axis
1932 // so ix,iy,dx and dy are inter exchanged 1949 // so ix,iy,dx and dy are inter exchanged
1950
1933 if (x < regsize - 1) 1951 if (x < regsize - 1)
1934 { 1952 {
1935 iy = (int)x; 1953 iy = (int)x;
@@ -1976,7 +1994,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1976 */ 1994 */
1977 h0 = ((float)heights[iy]); // 0,0 vertice 1995 h0 = ((float)heights[iy]); // 0,0 vertice
1978 1996
1979 if ((dy > dx)) 1997 if (dy>dx)
1980 { 1998 {
1981 iy += regsize; 1999 iy += regsize;
1982 h2 = (float)heights[iy]; // 0,1 vertice 2000 h2 = (float)heights[iy]; // 0,1 vertice
@@ -1994,6 +2012,133 @@ namespace OpenSim.Region.Physics.OdePlugin
1994 return h0 + h1 + h2; 2012 return h0 + h1 + h2;
1995 } 2013 }
1996 2014
2015 public Vector3 GetTerrainNormalAtXY(float x, float y)
2016 {
2017 int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2018 int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2019
2020 IntPtr heightFieldGeom = IntPtr.Zero;
2021 Vector3 norm = new Vector3(0, 0, 1);
2022
2023 // get region map
2024 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
2025 return norm;
2026
2027 if (heightFieldGeom == IntPtr.Zero)
2028 return norm;
2029
2030 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
2031 return norm;
2032
2033 // TerrainHeightField for ODE as offset 1m
2034 x += 1f - offsetX;
2035 y += 1f - offsetY;
2036
2037 // make position fit into array
2038 if (x < 0)
2039 x = 0;
2040 if (y < 0)
2041 y = 0;
2042
2043 // integer indexs
2044 int ix;
2045 int iy;
2046 // interpolators offset
2047 float dx;
2048 float dy;
2049
2050
2051 int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples
2052 int xstep = 1;
2053 int ystep = regsize;
2054 bool firstTri = false;
2055
2056 if (OdeUbitLib)
2057 {
2058 if (x < regsize - 1)
2059 {
2060 ix = (int)x;
2061 dx = x - (float)ix;
2062 }
2063 else // out world use external height
2064 {
2065 ix = regsize - 2;
2066 dx = 0;
2067 }
2068 if (y < regsize - 1)
2069 {
2070 iy = (int)y;
2071 dy = y - (float)iy;
2072 }
2073 else
2074 {
2075 iy = regsize - 2;
2076 dy = 0;
2077 }
2078 firstTri = dy > dx;
2079 }
2080
2081 else
2082 {
2083 xstep = regsize;
2084 ystep = 1;
2085 // we still have square fixed size regions
2086 // also flip x and y because of how map is done for ODE fliped axis
2087 // so ix,iy,dx and dy are inter exchanged
2088 if (x < regsize - 1)
2089 {
2090 iy = (int)x;
2091 dy = x - (float)iy;
2092 }
2093 else // out world use external height
2094 {
2095 iy = regsize - 2;
2096 dy = 0;
2097 }
2098 if (y < regsize - 1)
2099 {
2100 ix = (int)y;
2101 dx = y - (float)ix;
2102 }
2103 else
2104 {
2105 ix = regsize - 2;
2106 dx = 0;
2107 }
2108 firstTri = dx > dy;
2109 }
2110
2111 float h0;
2112 float h1;
2113 float h2;
2114
2115 iy *= regsize;
2116 iy += ix; // all indexes have iy + ix
2117
2118 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2119
2120 if (firstTri)
2121 {
2122 h1 = ((float)heights[iy]); // 0,0 vertice
2123 iy += ystep;
2124 h0 = (float)heights[iy]; // 0,1
2125 h2 = (float)heights[iy+xstep]; // 1,1 vertice
2126 norm.X = h0 - h2;
2127 norm.Y = h1 - h0;
2128 }
2129 else
2130 {
2131 h2 = ((float)heights[iy]); // 0,0 vertice
2132 iy += xstep;
2133 h0 = ((float)heights[iy]); // 1,0 vertice
2134 h1 = (float)heights[iy+ystep]; // vertice 1,1
2135 norm.X = h2 - h0;
2136 norm.Y = h0 - h1;
2137 }
2138 norm.Z = 1;
2139 norm.Normalize();
2140 return norm;
2141 }
1997 2142
1998 public override void SetTerrain(float[] heightMap) 2143 public override void SetTerrain(float[] heightMap)
1999 { 2144 {