public LSL_Vector llGroundNormal(LSL_Vector offset)
{
if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
(float)offset.y,
(float)offset.z);
ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
// Clamp to valid position
if (pos.X < 0)
pos.X = 0;
else if (pos.X >= heightmap.Width)
pos.X = heightmap.Width - 1;
if (pos.Y < 0)
pos.Y = 0;
else if (pos.Y >= heightmap.Height)
pos.Y = heightmap.Height - 1;
//Find two points in addition to the position to define a plane
Vector3 p0 = new Vector3(pos.X, pos.Y,
heightmap[(int)pos.X, (int)pos.Y]);
Vector3 p1 = new Vector3();
Vector3 p2 = new Vector3();
if ((pos.X + 1.0f) >= heightmap.Width)
p1 = new Vector3(pos.X + 1.0f, pos.Y,
heightmap[(int)pos.X, (int)pos.Y]);
else
p1 = new Vector3(pos.X + 1.0f, pos.Y,
heightmap[(int)(pos.X + 1.0f), (int)pos.Y]);
if ((pos.Y + 1.0f) >= heightmap.Height)
p2 = new Vector3(pos.X, pos.Y + 1.0f,
heightmap[(int)pos.X, (int)pos.Y]);
else
p2 = new Vector3(pos.X, pos.Y + 1.0f,
heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]);
//Find normalized vectors from p0 to p1 and p0 to p2
Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
// v0.Normalize();
// v1.Normalize();
//Find the cross product of the vectors (the slope normal).
Vector3 vsn = new Vector3
{
X = (v0.Y * v1.Z) - (v0.Z * v1.Y),
Y = (v0.Z * v1.X) - (v0.X * v1.Z),
Z = (v0.X * v1.Y) - (v0.Y * v1.X)
};
vsn.Normalize();
//I believe the crossproduct of two normalized vectors is a normalized vector so
//this normalization may be overkill
// then don't normalize them just the result
return new LSL_Vector(vsn.X, vsn.Y, vsn.Z);
}