public float Sample(Vector2D coord) { if (coord.X > 1) coord.X = 1; else if (coord.X < 0) coord.X = 0; if (coord.Y > 1) coord.Y = 1; else if (coord.Y < 0) coord.Y = 0; return SampleActual((int)(coord.X * (width - 1)), (int)(coord.Y * (height - 1))); }
public HeightFieldObject(Vector3D origin, MaterialShader shader, Vector2D size, Bitmap bitmapSrc) : base(origin, shader, -1) { this.bitmapSrc = bitmapSrc; // calculate bounds areaExtent = size; Vector2D halfSize = size * 0.5; areaStart = origin - halfSize; areaEnd = origin + halfSize; double szLen = size.Length(); radius = Math.Sqrt((szLen * szLen) + (1.1 * 1.1)) / 2; hField = HeightField.FromBitmap(bitmapSrc); onePx = new Vector2D(areaExtent.X / hField.Width, areaExtent.Y / hField.Height); this.origin.Y = 0.5; zMin = 0; zTop = 1; rectangles = new Rectangle3D[] { new Rectangle3D(new Vector3D(areaStart.X, zTop, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 1, 0), -zTop)), // top new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zMin, areaEnd.Y), new PlaneD(new Vector3D(0, -1, 0), zMin)), // bottom new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaStart.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(-1, 0, 0), halfSize.X)), // left new Rectangle3D(new Vector3D(areaEnd.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(1, 0, 0), -halfSize.X)), // right new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaStart.Y), new PlaneD(new Vector3D(0, 0, -1), halfSize.Y)), // front new Rectangle3D(new Vector3D(areaStart.X, zMin, areaEnd.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 0, 1), -halfSize.Y)), // back }; }
public override Vector2D GetTexCoord(Vector3D p, uint subIdx) { Vector2D coord = new Vector2D(p.X - areaStart.X, p.Z - areaStart.Y); coord.X /= areaExtent.X; coord.Y /= areaExtent.Y; return coord; }
public override Vector3D GetNormal(Vector3D pos, uint subIdx) { Vector2D coord = new Vector2D(pos.X - areaStart.X, pos.Z - areaStart.Y); coord.X /= areaExtent.X; coord.Y /= areaExtent.Y; // calc normal from surrounding pixels float val = hField.Sample(coord); float valxmin = hField.SampleShiftX(coord.X, coord.Y, -1); float valxmax = hField.SampleShiftX(coord.X, coord.Y, 1); Vector3D rightAngle = new Vector3D(0, 0, -1); Vector3D p1 = new Vector3D(onePx.X, valxmax - val, 0).Cross(rightAngle); Vector3D p2 = new Vector3D(-onePx.X, valxmin - val, 0).Cross(rightAngle); Vector3D xDir = Vector3D.Normalize(p1 - p2); float valymin = hField.SampleShiftY(coord.X, coord.Y, -1); float valymax = hField.SampleShiftY(coord.X, coord.Y, 1); rightAngle = new Vector3D(1, 0, 0); p1 = new Vector3D(0, valymax - val, onePx.Y).Cross(rightAngle); p2 = new Vector3D(0, valymin - val, -onePx.Y).Cross(rightAngle); Vector3D yDir = Vector3D.Normalize(p1 - p2); return Vector3D.Normalize(xDir + yDir); }