Beispiel #1
0
        static void SmearDirection(VoxelSet <float> voxels, float transference, Vec3i dir)
        {
            Vec3i dx = new Vec3i(Math.Abs(dir.y), Math.Abs(dir.z), Math.Abs(dir.x));
            Vec3i dy = new Vec3i(Math.Abs(dir.z), Math.Abs(dir.x), Math.Abs(dir.y));

            Vec3i start = new Vec3i(0);

            if (Vec3i.Dot(dir, new Vec3i(1)) < 0)
            {
                start = voxels.Size.Dot(dir) * dir + dir;
            }

            int y = 0;

            while (voxels.IsValid(start + y * dy))
            {
                int x = 0;
                while (voxels.IsValid(start + y * dy + x * dx))
                {
                    SmearLine(voxels, transference, dir, start + y * dy + x * dx);
                    x++;
                }
                y++;
            }
        }
Beispiel #2
0
        public static List <Box> MakeBoxes(VoxelSet <bool> shape)
        {
            List <Box> boxes = new List <Box>();

            // Directions to explore
            Vec3i[] dirs = new[] {
                new Vec3i(1, 0, 0),
                new Vec3i(0, 1, 0),
                new Vec3i(0, 0, 1)
            };

            // TODO: Iteration order may need to be reversed
            for (int z = 0; z < shape.Size.z; z++)
            {
                for (int y = 0; y < shape.Size.y; y++)
                {
                    for (int x = 0; x < shape.Size.x; x++)
                    {
                        if (!shape[x, y, z])
                        {
                            continue;
                        }

                        Vec3i idx    = new Vec3i(x, y, z);
                        Vec3i endIdx = new Vec3i(x, y, z);

                        // Expand box in each cardinal direction as much as possible
                        foreach (var dir in dirs)
                        {
                            Vec3i checkFromIdx = idx;

                            // Expand as much as possible in the current direction
                            while (shape.IsValid(endIdx + dir))
                            {
                                checkFromIdx += dir;

                                // Create a slice for the next layer in the current dir and make sure it's solid
                                var slice = shape.Slice(checkFromIdx, endIdx + dir);
                                if (!slice.IsAllSolid(b => b))
                                {
                                    break;
                                }
                                slice.Set(false);

                                endIdx += dir;
                            }
                        }

                        Box box = new Box();
                        box.origin  = new Vec3i(x, y, z);
                        box.extents = new Vec3i(endIdx.x + 1 - idx.x, endIdx.y + 1 - idx.y, endIdx.z + 1 - idx.z);
                        boxes.Add(box);
                    }
                }
            }

            return(boxes);
        }
Beispiel #3
0
        static void SmearLine(VoxelSet <float> voxels, float transference, Vec3i dir, Vec3i start)
        {
            Vec3i idx = start + dir;

            while (voxels.IsValid(idx))
            {
                voxels[idx] += voxels[idx - dir] * transference;
                idx         += dir;
            }
        }
Beispiel #4
0
    bool LayerMarch(Vector3 startPoint, Vector3 dir, out Vec3i hitIdx, out Vec3i lastIdx, ref float t)
    {
        dir = Vector3.Normalize(dir);

        Vector3 voxelGridSize = new Vector3(voxels.Size.x, voxels.Size.y, voxels.Size.z);

        Vector3 p0   = startPoint;
        float   endT = VecUtil.MinComp(Vector3.Max(
                                           VecUtil.Div(voxelGridSize - p0, dir),
                                           VecUtil.Div(-p0, dir)
                                           ));

        Vector3 dirAbs = VecUtil.Abs(dir);

        // TODO: This is making invalid assumptions about p0
        //Vector3 p0abs = VecUtil.Mul(Vector3.one - VecUtil.Step(0, dir), voxelGridSize)
        //    + VecUtil.Mul(VecUtil.Sign(dir), p0);

        //Vector3 negativeDimensions = Vector3.one - VecUtil.Step(0, dir);
        //Vector3 p0abs = VecUtil.Mul(negativeDimensions, voxelGridSize) - VecUtil.Mul(negativeDimensions, p0)
        //+ VecUtil.Mul(VecUtil.Step(0, dir), p0);

        Vector3 p0abs = p0;

        for (int i = 0; i < 3; ++i)
        {
            if (dir[i] < 0)
            {
                p0abs[i] = voxelGridSize[i] - p0[i];
            }
        }

        //float t = 0;
        //t = 0;
        lastIdx = ToIndex(p0 + dir * (t - kEps));
        int            iterationCount = 0;
        List <Vector3> debugPos       = new List <Vector3>();
        List <Vector3> debugPosAbs    = new List <Vector3>();

        t += kEps;

        while (t <= endT)
        {
            Vec3i idx = ToIndex(p0 + dir * (t + kEps));
            debugPos.Add(p0 + dir * (t + kEps));
            //Vec3i idx = ToIndex(p0 + dir * t);

            debugPosAbs.Add(p0abs + dirAbs * (t + kEps));
            Vector3 pAbs = p0abs + dirAbs * (t + kEps);

            ////////////////
            // DEBUG CODE
            Vec3i delta = idx - lastIdx;
            if (Vec3i.Dot(delta, delta) > 1)
            {
                Debug.LogWarning("Skipped a voxel");
            }

            if (!voxels.IsValid(idx))
            {
                break;
            }

            Color32 c = voxels[idx];
            if (c.a > 0)
            {
                hitIdx = idx;
                return(true);
            }

            lastIdx = idx;

            // Pretend we came in from a positive direction

            //Vector3 pAbs = p0abs + dirAbs * (t);
            Vector3 deltas = VecUtil.Div(Vector3.one - VecUtil.Fract(pAbs), dirAbs);
            //t += Mathf.Max(VecUtil.MinComp(deltas), float.Epsilon);
            //t += Mathf.Max(VecUtil.MinComp(deltas), 0.0005f);
            t += Mathf.Max(VecUtil.MinComp(deltas), kEps) + kEps;

            //Vector3 pAbs = p0abs + dirAbs * t;
            //Vector3 deltas = VecUtil.Div(Vector3.one - VecUtil.Fract(pAbs), dirAbs);
            //t += Mathf.Max(VecUtil.MinComp(deltas), float.Epsilon);

            //Vector3 pAbs = p0abs + dirAbs * t;
            //Vector3 p = p0 + dir * t;
            //Vector3 deltas = VecUtil.Div(VecUtil.Step(0, dir) - VecUtil.Fract(p), dir);
            //t += Mathf.Max(VecUtil.MinComp(deltas), 0.0005f);
            //t += Mathf.Max(VecUtil.MinComp(deltas), float.Epsilon);
            iterationCount++;
        }

        hitIdx = new Vec3i(-1);
        return(false);
    }
Beispiel #5
0
        public static List <Quad> VoxelsToQuads(VoxelSet <Vec4b> voxels)
        {
            List <Quad> quads = new List <Quad>();

            Vec3f[] normals =
            {
                new Vec3f(1,   0, 0),
                new Vec3f(-1,  0, 0),
                new Vec3f(0,   1, 0),
                new Vec3f(0,  -1, 0),
                new Vec3f(0,   0, 1),
                new Vec3f(0,   0, -1)
            };

            Vec3f[] dxs =
            {
                new Vec3f(0, 1, 0),
                new Vec3f(0, 0, 1),
                new Vec3f(0, 0, 1),
                new Vec3f(1, 0, 0),
                new Vec3f(1, 0, 0),
                new Vec3f(0, 1, 0)
            };

            Vec3f[] dys =
            {
                new Vec3f(0, 0, 1),
                new Vec3f(0, 1, 0),
                new Vec3f(1, 0, 0),
                new Vec3f(0, 0, 1),
                new Vec3f(0, 1, 0),
                new Vec3f(1, 0, 0)
            };

            voxels.Apply((Vec4b c, Vec3i idx) => {
                if (c.w == 0)
                {
                    // Voxel is empty
                    //return;
                }

                // Check each face
                for (int i = 0; i < 6; ++i)
                {
                    Quad quad   = new Quad();
                    quad.normal = normals[i];
                    quad.dx     = dxs[i];
                    quad.dy     = dys[i];
                    quad.offset = new Vec3f(idx.x, idx.y, idx.z);
                    quad.color  = c;

                    Vec3i neighbor = idx + new Vec3i(new Vec3f(quad.normal.x, quad.normal.y, quad.normal.z));
                    if (c.w == 0 || voxels.IsValid(neighbor) && voxels[neighbor].w > 0)
                    {
                        // Voxel face is covered
                        continue;
                    }

                    if (quad.normal.x > 0 || quad.normal.y > 0 || quad.normal.z > 0)
                    {
                        quad.offset += quad.normal;
                    }

                    quads.Add(quad);
                }
            });

            return(quads);
        }
Beispiel #6
0
    ////////////////////////////////////////////////////////////////////////////



    // Adds all faces for the given index of the given voxels to the list of quads.
    static void AddFaces(VoxelSet <Vec4b> voxels, List <Quad> quads, Vec3i idx)
    {
        Vec3i[] normals =
        {
            new Vec3i(1,   0, 0),
            new Vec3i(-1,  0, 0),

            new Vec3i(0,   1, 0),
            new Vec3i(0,  -1, 0),

            new Vec3i(0,   0, 1),
            new Vec3i(0,   0, -1)
        };

        bool transparent = IsTransparent(voxels, idx);

        for (int i = 0; i < normals.Length; ++i)
        {
            Vec3i normal   = normals[i];
            Vec3i neighbor = idx + normal;
            if (voxels.IsValid(neighbor) && (voxels[neighbor].w > 0))
            {
                if (transparent && IsTransparent(voxels, neighbor))
                {
                    // Two transparent voxels - face is hidden.
                    continue;
                }

                if (transparent && voxels[neighbor].w == 255)
                {
                    // Transparent self and opaque neighbor - hidden to avoid z-fighting.
                    continue;
                }

                if (!transparent && voxels[neighbor].w == 255)
                {
                    // Two opaque voxels - face is hidden.
                    continue;
                }
            }

            var  c = voxels[idx];
            Quad q = new Quad();

            q.color = new Color32(c.x, c.y, c.z, c.w);

            Vec3i pos = idx;

            if (Vec3i.Dot(normal, new Vec3i(1)) > 0)
            {
                pos += normal;
            }

            q.position = new Vector3(pos.x, pos.y, pos.z);
            q.uv       = new Vector2(i, 0);

            quads.Add(q);

            if (transparent)
            {
                // Add back facing as well for transparent quads
                //q.uv = new Vector2((i - (i % 2)) + ((i + 1) % 2), 0);
                q.uv = new Vector2(i ^ 1, 0);
                //q.position += new Vector3(normal.x, normal.y, normal.z);
                quads.Add(q);
            }
        }
    }