Пример #1
0
        /// <summary>
        /// Intersect a ray against this object.
        /// </summary>
        /// <param name="start">The start position of the ray, in object space.</param>
        /// <param name="dir">The direction of the ray, in object space (not a unit vector).</param>
        /// <returns>Information about the nearest intersection, or null if no intersection.</returns>
        public IntersectionInfo IntersectRay(Vector start, Vector dir, RenderContext context)
        {
            // TODO: some rays should be short (e.g. ambient occlusion rays). Make the max ray distance an optional parameter?
            Vector end = start + dir * 10;

            //if (!boundingBox.OverlapsLineSegment(start, end))
            // TODO: clipping line segment breaks IntersectionInfo.rayFrac, because ray is truncated, but rayFrac does not reflect this!
            if (!boundingBox.ClipLineSegment(ref start, ref end))
            {
                return(null);
            }

            // Scale up from (unit) object space to voxel grid resolution
            var half = new Vector(0.5, 0.5, 0.5);

            start = (start * 0.5 + half) * ((double)GridSize - 0.001);
            end   = (end * 0.5 + half) * ((double)GridSize - 0.001);

            int oldX = -1, oldY = -1, oldZ = -1;

            // TODO: a larger minStep (e.g. 1) makes the voxels look like thin squares facing a single direction. Why?
            foreach (var pos in LineWalker3D.WalkLine(start, end, 0.1))
            {
                int x = (int)pos.x;
                var y = (int)pos.y;
                var z = (int)pos.z;
                Contract.Assert(x >= 0 && x < GridSize && y >= 0 && y < GridSize && z >= 0 && z < GridSize);

                // TODO: Contracts analyser says pos.z is not -1 here, and similarly for x and y
                if (x != oldX && y != oldY && z != oldZ)
                {
                    uint colorSample = voxelColors[x, y, z];

                    // Treat black voxels as transparent
                    if (colorSample != 0)
                    {
                        //var normal = new Vector(oldX - x, oldY - y, oldZ - z);
                        //normal.Normalise();

                        var normal = voxelNormals[x, y, z];
                        Contract.Assume(normal.IsUnitVector);

                        // DEBUGGING: visualise normals
                        //colorSample = new Color(normal.x, normal.y, normal.z).ToARGB();

                        // TODO: also return correct rayFrac, pos and normal
                        return(new IntersectionInfo {
                            color = colorSample, normal = normal                           /*, pos = pos, rayFrac = (pos - start).Length */
                        });
                        //return new IntersectionInfo { color = sample, pos = pos, rayFrac = (pos - start).Length, normal = Vector.Up };
                    }
                }
            }

            return(null);
        }
Пример #2
0
        // Test line walking by drawing lots of 2D lines on a view, to see how they look.
        public static void TestLineWalking(Surface view)
        {
            Contract.Requires(view != null);
            const int jump = 10;

            for (int col = 0; col < view.Width - 1; col++)
            {
                view.DrawPixel(col, 0, Color.Pink.ToARGB());
                view.DrawPixel(col, view.Height - 1, Color.Pink.ToARGB());
            }

            for (int col = 0; col < view.Height - 1; col++)
            {
                view.DrawPixel(0, col, Color.Cyan.ToARGB());
                view.DrawPixel(view.Width - 1, col, Color.Cyan.ToARGB());
            }

            for (int col = 0; col < view.Width / jump; col++)
            {
                foreach (var pt in LineWalker3D.WalkLine(new Vector(col * jump, 0, 0), new Vector(view.Width / 2, view.Height / 2, 0)))
                {
                    view.DrawPixel((int)(pt.x + 0.5), (int)(pt.y + 0.5), Color.Blue.ToARGB());
                }

/*
 *              foreach (var pt in LineWalker3D.WalkLine(col * jump, view.Height - 1, view.Width / 2, view.Height / 2))
 *              {
 *                  view.DrawViewPixel((int)(pt.x + 0.5), (int)(pt.y + 0.5), Color.Green.ToARGB());
 *              }
 */
            }

/*
 *          for (int col = 0; col < view.Height / jump; col++)
 *          {
 *              foreach (var pt in LineWalker3D.WalkLine(0, col * jump, view.Width / 2, view.Height / 2))
 *              {
 *                  view.DrawViewPixel((int)(pt.x + 0.5), (int)(pt.y + 0.5), Color.Red.ToARGB());
 *              }
 *
 *              foreach (var pt in LineWalker3D.WalkLine(view.Width - 1, col * jump, view.Width / 2, view.Height / 2))
 *              {
 *                  view.DrawViewPixel((int)(pt.x + 0), (int)(pt.y + 0), Color.Yellow.ToARGB());
 *              }
 *          }
 */


            //for (int row = 0; row < view.Height; row++)
            //{
            //    for (int col = 0; col < view.Width; col++)
            //    {
            //        Vector start = new Vector(mouseViewPos.x, mouseViewPos.y);
            //        Vector end = new Vector(col, row);
            //        var hitPt = map.IntersectWorldLine(start, end, 1);
            //        var color = hitPt.IsInvalid() ? Color.Red : Color.Green;

            //        //var color = map.IsSolidTile(col, row) ? Color.Red : Color.Green;

            //        view.DrawViewPixel(col, row, color.ToARGB());
            //    }
            //}
        }