Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster

avinationmerge
Melanie 2012-04-23 21:13:08 +01:00
commit 159b3b27ca
7 changed files with 663 additions and 548 deletions

View File

@ -149,27 +149,47 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
public void SelectPrim(uint primLocalID, IClientAPI remoteClient) public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
{ {
/*
SceneObjectPart part = GetSceneObjectPart(primLocalID);
if (null == part)
return;
if (part.IsRoot)
{
SceneObjectGroup sog = part.ParentGroup;
sog.SendPropertiesToClient(remoteClient);
// A prim is only tainted if it's allowed to be edited by the person clicking it.
if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
|| Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
{
sog.IsSelected = true;
EventManager.TriggerParcelPrimCountTainted();
}
}
else
{
part.SendPropertiesToClient(remoteClient);
}
*/
SceneObjectPart part = GetSceneObjectPart(primLocalID); SceneObjectPart part = GetSceneObjectPart(primLocalID);
if (null == part) if (null == part)
return; return;
if (part.IsRoot) SceneObjectGroup sog = part.ParentGroup;
{ if (sog == null)
SceneObjectGroup sog = part.ParentGroup; return;
sog.SendPropertiesToClient(remoteClient);
// A prim is only tainted if it's allowed to be edited by the person clicking it. part.SendPropertiesToClient(remoteClient);
if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
|| Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) // A prim is only tainted if it's allowed to be edited by the person clicking it.
{ if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
sog.IsSelected = true; || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
EventManager.TriggerParcelPrimCountTainted();
}
}
else
{ {
part.SendPropertiesToClient(remoteClient); part.IsSelected = true;
EventManager.TriggerParcelPrimCountTainted();
} }
} }
@ -222,7 +242,7 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart part = GetSceneObjectPart(primLocalID); SceneObjectPart part = GetSceneObjectPart(primLocalID);
if (part == null) if (part == null)
return; return;
/*
// A deselect packet contains all the local prims being deselected. However, since selection is still // A deselect packet contains all the local prims being deselected. However, since selection is still
// group based we only want the root prim to trigger a full update - otherwise on objects with many prims // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
// we end up sending many duplicate ObjectUpdates // we end up sending many duplicate ObjectUpdates
@ -257,6 +277,22 @@ namespace OpenSim.Region.Framework.Scenes
part.UUID, remoteClient.AgentId)) part.UUID, remoteClient.AgentId))
EventManager.TriggerParcelPrimCountTainted(); EventManager.TriggerParcelPrimCountTainted();
} }
*/
bool oldgprSelect = part.ParentGroup.IsSelected;
// This is wrong, wrong, wrong. Selection should not be
// handled by group, but by prim. Legacy cruft.
// TODO: Make selection flagging per prim!
//
if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
|| Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
{
part.IsSelected = false;
if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
EventManager.TriggerParcelPrimCountTainted();
}
} }
public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,

View File

@ -726,6 +726,11 @@ namespace OpenSim.Region.Framework.Scenes
m_isSelected = value; m_isSelected = value;
// Tell physics engine that group is selected // Tell physics engine that group is selected
// this is not right
// but ode engines should only really need to know about root part
// so they can put entire object simulation on hold and not colliding
// keep as was for now
PhysicsActor pa = m_rootPart.PhysActor; PhysicsActor pa = m_rootPart.PhysActor;
if (pa != null) if (pa != null)
{ {
@ -747,6 +752,40 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void PartSelectChanged(bool partSelect)
{
// any part selected makes group selected
if (m_isSelected == partSelect)
return;
if (partSelect)
{
IsSelected = partSelect;
// if (!IsAttachment)
// ScheduleGroupForFullUpdate();
}
else
{
// bad bad bad 2 heavy for large linksets
// since viewer does send lot of (un)selects
// this needs to be replaced by a specific list or count ?
// but that will require extra code in several places
SceneObjectPart[] parts = m_parts.GetArray();
for (int i = 0; i < parts.Length; i++)
{
SceneObjectPart part = parts[i];
if (part.IsSelected)
return;
}
IsSelected = partSelect;
if (!IsAttachment)
{
ScheduleGroupForFullUpdate();
}
}
}
private SceneObjectPart m_PlaySoundMasterPrim = null; private SceneObjectPart m_PlaySoundMasterPrim = null;
public SceneObjectPart PlaySoundMasterPrim public SceneObjectPart PlaySoundMasterPrim
{ {
@ -3161,14 +3200,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/*
RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
for (int i = 0; i < parts.Length; i++)
{
if (parts[i] != RootPart)
parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
}
*/
if (parts.Length > 1) if (parts.Length > 1)
{ {
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
@ -3185,7 +3216,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false); m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
} }
} }

View File

@ -304,6 +304,9 @@ namespace OpenSim.Region.Framework.Scenes
protected float m_friction = 0.6f; // wood protected float m_friction = 0.6f; // wood
protected float m_bounce = 0.5f; // wood protected float m_bounce = 0.5f; // wood
protected bool m_isSelected = false;
/// <summary> /// <summary>
/// Stores media texture data /// Stores media texture data
/// </summary> /// </summary>
@ -577,6 +580,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public bool IsSelected
{
get { return m_isSelected; }
set
{
m_isSelected = value;
if (ParentGroup != null)
ParentGroup.PartSelectChanged(value);
}
}
public Dictionary<int, string> CollisionFilter public Dictionary<int, string> CollisionFilter
@ -1907,6 +1920,7 @@ namespace OpenSim.Region.Framework.Scenes
dupe.m_rezzed = m_rezzed; dupe.m_rezzed = m_rezzed;
dupe.m_UndoRedo = null; dupe.m_UndoRedo = null;
dupe.m_isSelected = false;
dupe.IgnoreUndoUpdate = false; dupe.IgnoreUndoUpdate = false;
dupe.Undoing = false; dupe.Undoing = false;

View File

@ -753,9 +753,10 @@ namespace OpenSim.Region.Framework.Scenes
if (m_movementAnimationUpdateCounter >= 2) if (m_movementAnimationUpdateCounter >= 2)
{ {
m_movementAnimationUpdateCounter = 0; m_movementAnimationUpdateCounter = 0;
if (Animator != null && ParentID == 0) // skip it if sitting if (Animator != null)
{ {
Animator.UpdateMovementAnimations(); if(ParentID == 0) // skip it if sitting
Animator.UpdateMovementAnimations();
} }
else else
{ {
@ -1400,6 +1401,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
// m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); // m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT; Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT;
Vector3 distTocam = CameraPosition - posAdjusted; Vector3 distTocam = CameraPosition - posAdjusted;
float distTocamlen = distTocam.Length(); float distTocamlen = distTocam.Length();
@ -1408,6 +1410,7 @@ namespace OpenSim.Region.Framework.Scenes
distTocam *= 1.0f / distTocamlen; distTocam *= 1.0f / distTocamlen;
m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback); m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback);
} }
} }
} }

View File

@ -686,6 +686,9 @@ namespace OpenSim.Region.Physics.OdePlugin
Body = d.BodyCreate(_parent_scene.world); Body = d.BodyCreate(_parent_scene.world);
_zeroFlag = false;
m_pidControllerActive = true;
d.BodySetAutoDisableFlag(Body, false); d.BodySetAutoDisableFlag(Body, false);
d.BodySetPosition(Body, npositionX, npositionY, npositionZ); d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
@ -862,12 +865,12 @@ namespace OpenSim.Region.Physics.OdePlugin
float depth = terrainheight - chrminZ; float depth = terrainheight - chrminZ;
if (!flying) if (!flying)
{ {
vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 60; vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 50;
} }
else else
vec.Z = depth * PID_P * 60; vec.Z = depth * PID_P * 50;
if (depth < 0.2f) if (depth < 0.1f)
{ {
m_iscolliding = true; m_iscolliding = true;
m_colliderfilter = 2; m_colliderfilter = 2;
@ -1009,9 +1012,17 @@ namespace OpenSim.Region.Physics.OdePlugin
// update our local ideia of position velocity and aceleration // update our local ideia of position velocity and aceleration
_position = localpos; _position = localpos;
_acceleration = _velocity; // previus velocity if (_zeroFlag)
_velocity = vel; {
_acceleration = (vel - _acceleration) / timeStep; _velocity = Vector3.Zero;
_acceleration = Vector3.Zero;
}
else
{
_acceleration = _velocity; // previus velocity
_velocity = vel;
_acceleration = (vel - _acceleration) / timeStep;
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -189,9 +189,12 @@ namespace OpenSim.Region.Physics.OdePlugin
private const uint m_regionHeight = Constants.RegionSize; private const uint m_regionHeight = Constants.RegionSize;
public float ODE_STEPSIZE = 0.020f; public float ODE_STEPSIZE = 0.020f;
public float HalfOdeStep = 0.01f;
private float metersInSpace = 25.6f; private float metersInSpace = 25.6f;
private float m_timeDilation = 1.0f; private float m_timeDilation = 1.0f;
DateTime m_lastframe;
public float gravityx = 0f; public float gravityx = 0f;
public float gravityy = 0f; public float gravityy = 0f;
public float gravityz = -9.8f; public float gravityz = -9.8f;
@ -485,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
HalfOdeStep = ODE_STEPSIZE * 0.5f;
ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf); ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf); GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf);
@ -521,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.WorldSetAngularDamping(world, 0.001f); d.WorldSetAngularDamping(world, 0.001f);
d.WorldSetAngularDampingThreshold(world, 0f); d.WorldSetAngularDampingThreshold(world, 0f);
d.WorldSetLinearDampingThreshold(world, 0f); d.WorldSetLinearDampingThreshold(world, 0f);
d.WorldSetMaxAngularSpeed(world, 256f); d.WorldSetMaxAngularSpeed(world, 100f);
d.WorldSetCFM(world,1e-6f); // a bit harder than default d.WorldSetCFM(world,1e-6f); // a bit harder than default
//d.WorldSetCFM(world, 1e-4f); // a bit harder than default //d.WorldSetCFM(world, 1e-4f); // a bit harder than default
@ -564,6 +569,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// let this now be real maximum values // let this now be real maximum values
spaceGridMaxX--; spaceGridMaxX--;
spaceGridMaxY--; spaceGridMaxY--;
m_lastframe = DateTime.UtcNow;
} }
internal void waitForSpaceUnlock(IntPtr space) internal void waitForSpaceUnlock(IntPtr space)
@ -1685,35 +1691,30 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <returns></returns> /// <returns></returns>
public override float Simulate(float timeStep) public override float Simulate(float timeStep)
{ {
int statstart;
int statchanges = 0;
int statchmove = 0;
int statactmove = 0;
int statray = 0;
int statcol = 0;
int statstep = 0;
int statmovchar = 0;
int statmovprim;
int totjcontact = 0;
DateTime now = DateTime.UtcNow;
TimeSpan SinceLastFrame = now - m_lastframe;
m_lastframe = now;
timeStep = (float)SinceLastFrame.TotalSeconds;
// acumulate time so we can reduce error // acumulate time so we can reduce error
step_time += timeStep; step_time += timeStep;
if (step_time < ODE_STEPSIZE) if (step_time < HalfOdeStep)
return 0; return 0;
if (framecount >= int.MaxValue) if (framecount < 0)
framecount = 0; framecount = 0;
framecount++; framecount++;
int curphysiteractions = m_physicsiterations; int curphysiteractions;
// if in trouble reduce step resolution
if (step_time >= m_SkipFramesAtms) if (step_time >= m_SkipFramesAtms)
{ curphysiteractions = m_physicsiterations / 2;
// if in trouble reduce step resolution else
curphysiteractions /= 2; curphysiteractions = m_physicsiterations;
}
int nodeframes = 0; int nodeframes = 0;
@ -1733,13 +1734,10 @@ namespace OpenSim.Region.Physics.OdePlugin
base.TriggerPhysicsBasedRestart(); base.TriggerPhysicsBasedRestart();
} }
while (step_time >= HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
while (step_time >= ODE_STEPSIZE && nodeframes < 10) //limit number of steps so we don't say here for ever
{ {
try try
{ {
statstart = Util.EnvironmentTickCount();
// clear pointer/counter to contacts to pass into joints // clear pointer/counter to contacts to pass into joints
m_global_contactcount = 0; m_global_contactcount = 0;
@ -1778,17 +1776,39 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
statchanges += Util.EnvironmentTickCountSubtract(statstart); // Move characters
lock (_characters)
{
List<OdeCharacter> defects = new List<OdeCharacter>();
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
actor.Move(ODE_STEPSIZE, defects);
}
if (defects.Count != 0)
{
foreach (OdeCharacter defect in defects)
{
RemoveCharacter(defect);
}
}
}
// Move other active objects
lock (_activegroups)
{
foreach (OdePrim aprim in _activegroups)
{
aprim.Move();
}
}
statactmove += Util.EnvironmentTickCountSubtract(statstart);
//if ((framecount % m_randomizeWater) == 0) //if ((framecount % m_randomizeWater) == 0)
// randomizeWater(waterlevel); // randomizeWater(waterlevel);
m_rayCastManager.ProcessQueuedRequests(); m_rayCastManager.ProcessQueuedRequests();
statray += Util.EnvironmentTickCountSubtract(statstart);
collision_optimized(); collision_optimized();
statcol += Util.EnvironmentTickCountSubtract(statstart);
lock (_collisionEventPrim) lock (_collisionEventPrim)
{ {
@ -1813,38 +1833,39 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
// do a ode simulation step
d.WorldQuickStep(world, ODE_STEPSIZE); d.WorldQuickStep(world, ODE_STEPSIZE);
statstep += Util.EnvironmentTickCountSubtract(statstart); d.JointGroupEmpty(contactgroup);
// Move characters // update managed ideia of physical data and do updates to core
lock (_characters) /*
lock (_characters)
{
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
{
if (actor.bad)
m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
actor.UpdatePositionAndVelocity();
}
}
}
*/
lock (_activegroups)
{ {
List<OdeCharacter> defects = new List<OdeCharacter>();
foreach (OdeCharacter actor in _characters)
{ {
if (actor != null) foreach (OdePrim actor in _activegroups)
actor.Move(ODE_STEPSIZE, defects);
}
if (defects.Count != 0)
{
foreach (OdeCharacter defect in defects)
{ {
RemoveCharacter(defect); if (actor.IsPhysical)
{
actor.UpdatePositionAndVelocity();
}
} }
} }
} }
statchmove += Util.EnvironmentTickCountSubtract(statstart);
// Move other active objects
lock (_activegroups)
{
foreach (OdePrim aprim in _activegroups)
{
aprim.Move();
}
}
//ode.dunlock(world);
} }
catch (Exception e) catch (Exception e)
{ {
@ -1852,32 +1873,11 @@ namespace OpenSim.Region.Physics.OdePlugin
// ode.dunlock(world); // ode.dunlock(world);
} }
d.JointGroupEmpty(contactgroup);
totjcontact += m_global_contactcount;
step_time -= ODE_STEPSIZE; step_time -= ODE_STEPSIZE;
nodeframes++; nodeframes++;
} }
statstart = Util.EnvironmentTickCount();
/*
// now included in characters move() and done at ode rate
// maybe be needed later if we need to do any extra work at hearbeat rate
lock (_characters)
{
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
{
if (actor.bad)
m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
actor.UpdatePositionAndVelocity();
}
}
}
*/
lock (_badCharacter) lock (_badCharacter)
{ {
if (_badCharacter.Count > 0) if (_badCharacter.Count > 0)
@ -1890,22 +1890,6 @@ namespace OpenSim.Region.Physics.OdePlugin
_badCharacter.Clear(); _badCharacter.Clear();
} }
} }
statmovchar = Util.EnvironmentTickCountSubtract(statstart);
lock (_activegroups)
{
{
foreach (OdePrim actor in _activegroups)
{
if (actor.IsPhysical)
{
actor.UpdatePositionAndVelocity((float)nodeframes * ODE_STEPSIZE);
}
}
}
}
statmovprim = Util.EnvironmentTickCountSubtract(statstart);
int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
@ -1932,15 +1916,17 @@ namespace OpenSim.Region.Physics.OdePlugin
d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
} }
// think time dilation is not a physics issue alone.. but ok let's fake something // think time dilation as to do with dinamic step size that we dont' have
if (step_time < ODE_STEPSIZE) // we did the required loops // even so tell something to world
if (nodeframes < 10) // we did the requested loops
m_timeDilation = 1.0f; m_timeDilation = 1.0f;
else else if (step_time > 0)
{ // we didn't forget the lost ones and let user know something {
m_timeDilation = 1 - step_time / timeStep; m_timeDilation = timeStep / step_time;
if (m_timeDilation < 0) if (m_timeDilation > 1)
m_timeDilation = 0; m_timeDilation = 1;
step_time = 0; if (step_time > m_SkipFramesAtms)
step_time = 0;
} }
} }
@ -2007,7 +1993,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else // out world use external height else // out world use external height
{ {
ix = regsize - 1; ix = regsize - 2;
dx = 0; dx = 0;
} }
if (y < regsize - 1) if (y < regsize - 1)
@ -2017,7 +2003,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
iy = regsize - 1; iy = regsize - 2;
dy = 0; dy = 0;
} }
} }
@ -2034,7 +2020,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else // out world use external height else // out world use external height
{ {
iy = regsize - 1; iy = regsize - 2;
dy = 0; dy = 0;
} }
if (y < regsize - 1) if (y < regsize - 1)
@ -2044,7 +2030,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
else else
{ {
ix = regsize - 1; ix = regsize - 2;
dx = 0; dx = 0;
} }
} }
@ -2057,18 +2043,35 @@ namespace OpenSim.Region.Physics.OdePlugin
iy += ix; // all indexes have iy + ix iy += ix; // all indexes have iy + ix
float[] heights = TerrainHeightFieldHeights[heightFieldGeom]; float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
/*
if ((dx + dy) <= 1.0f)
{
h0 = ((float)heights[iy]); // 0,0 vertice
h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
}
else
{
h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
}
*/
h0 = ((float)heights[iy]); // 0,0 vertice
if ((dx + dy) <= 1.0f) if ((dy > dx))
{ {
h0 = ((float)heights[iy]); // 0,0 vertice iy += regsize;
h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0 h2 = (float)heights[iy]; // 0,1 vertice
h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
} }
else else
{ {
h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice iy++;
h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0 h2 = (float)heights[iy]; // vertice 1,0
h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
} }
return h0 + h1 + h2; return h0 + h1 + h2;