Пример #1
0
        public void XYZ()
        {
            VoxelRotation rot = new VoxelRotation();

            Assert.AreEqual(0, rot.y);
            Assert.AreEqual(0, rot.x);
            Assert.AreEqual(0, rot.z);

            rot.x = 3;
            rot.y = 2;
            rot.z = 1;
            Assert.AreEqual(3, rot.x);
            Assert.AreEqual(2, rot.y);
            Assert.AreEqual(1, rot.z);

            rot.x -= 1;
            Assert.AreEqual(2, rot.x);
            Assert.AreEqual(2, rot.y);
            Assert.AreEqual(1, rot.z);
            rot.y += 1;
            Assert.AreEqual(2, rot.x);
            Assert.AreEqual(3, rot.y);
            Assert.AreEqual(1, rot.z);
            rot.z += 1;
            Assert.AreEqual(2, rot.x);
            Assert.AreEqual(3, rot.y);
            Assert.AreEqual(2, rot.z);
        }
Пример #2
0
        public void Z()
        {
            VoxelRotation rot = new VoxelRotation();

            Assert.AreEqual(0, rot.x);
            Assert.AreEqual(0, rot.y);
            Assert.AreEqual(0, rot.z);

            rot.z = 3;
            Assert.AreEqual(3, rot.z);
            rot.z -= 1;
            Assert.AreEqual(2, rot.z);
        }
Пример #3
0
 public void Blank()
 {
     for (int i = 0; i < 3; i++)
     {
         for (int j = 0; j < 3; j++)
         {
             for (int k = 0; k < 3; k++)
             {
                 var rot = new VoxelRotation()
                 {
                     x = i, y = j, z = k
                 };
                 bool empty = i == 0 && j == 0 && k == 0;
                 Assert.AreEqual(empty, rot.isBlank, $"Rotation isBlank method returned an unexpected result for x={i},y={j},z={k}");
             }
         }
     }
 }
Пример #4
0
        private void AddMeshDataForVoxel(ushort id, int3 position, bool rotated, VoxelRotation rotation)
        {
            var meshID     = data.meshDatabase.voxelTypeToMeshTypeMap[id];
            var faceZRange = data.voxelTypeDatabase.voxelTypeToZIndicesRangeMap[id];
            var materialID = data.meshDatabase.voxelTypeToMaterialIDMap[id];

            var meshRange = data.meshDatabase.meshTypeRanges[meshID];

            //Update the material run tracker
            runTracker.Update(materialID, data.materialRuns, data.allTriangleIndices);


            if (rotated)
            {
                //Add single rotated voxels data
                for (byte dir = 0; dir < numDirections; dir++)
                {
                    var rotatedDirection = (byte)directionHelper.GetDirectionAfterRotation((Direction)dir, rotation);
                    var faceIsSolid      = data.meshDatabase.isFaceSolid[meshRange.start + rotatedDirection];
                    if (IncludeFace(id, position, rotatedDirection, faceIsSolid))
                    {
                        AddFaceRotated(meshID, data.voxelTypeDatabase.zIndicesPerFace[faceZRange.start + dir], dir, position, rotation);
                    }
                }
            }
            else
            {
                //Add single voxel's data
                for (int dir = 0; dir < numDirections; dir++)
                {
                    var faceIsSolid = data.meshDatabase.isFaceSolid[meshRange.start + dir];
                    if (IncludeFace(id, position, dir, faceIsSolid))
                    {
                        AddFace(meshID, data.voxelTypeDatabase.zIndicesPerFace[faceZRange.start + dir], dir, position);
                    }
                }
            }
        }
Пример #5
0
        public void Inverse()
        {
            using (var directionHelper = DirectionRotatorExtensions.Create())
            {
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        for (int k = 0; k < 4; k++)
                        {
                            var rotation = new VoxelRotation()
                            {
                                x = i, y = j, z = k
                            };
                            var testDirection = Direction.north;

                            var thereAndBackAgain = directionHelper.GetDirectionBeforeRotation(directionHelper.GetDirectionAfterRotation(testDirection, rotation), rotation);

                            Assert.AreEqual(testDirection, thereAndBackAgain, $"Failed to invert rotation {rotation}");
                        }
                    }
                }
            }
        }
Пример #6
0
        public void Execute()
        {
            //Sort the rotated voxels so that they are in the order of iteration
            if (data.rotatedVoxels.Length > 0)
            {
                data.rotatedVoxels.Sort(new RotatedVoxelComparer());
            }
            int currentRotatedIndex = 0;

            runTracker = new MaterialRunTracker();

            int i = 0;//current index into voxelData

            for (int z = 0; z < data.dimensions.z; z++)
            {
                for (int y = 0; y < data.dimensions.y; y++)
                {
                    for (int x = 0; x < data.dimensions.x; x++)
                    {
                        var voxelTypeID = data.voxels[i];

                        if (voxelTypeID != VoxelTypeID.AIR_ID)
                        {
                            bool          rotated  = false;
                            VoxelRotation rotation = default;
                            if (data.rotatedVoxels.Length > 0 && data.rotatedVoxels[currentRotatedIndex].flatIndex == i)
                            {
                                //This voxel is rotated
                                rotated  = true;
                                rotation = data.rotatedVoxels[currentRotatedIndex].rotation;
                                AdvanceRotatedIndex(ref currentRotatedIndex);
                            }

                            if (data.voxelTypeDatabase.voxelTypeToIsPassableMap[voxelTypeID])
                            {
                                //Save non-collidable voxels for later, so that they appear contiguously in the mesh arrays
                                nonCollidableQueue.Add(new DoLater()
                                {
                                    position = new int3(x, y, z),
                                    typeID   = voxelTypeID,
                                    rotated  = rotated,
                                    rotation = rotation
                                });
                            }
                            else
                            {
                                AddMeshDataForVoxel(voxelTypeID, new int3(x, y, z), rotated, rotation);
                            }
                        }

                        i++;
                    }
                }
            }
            //Record length of collidable mesh section
            data.collisionSubmesh.Record(data.vertices.Length, data.allTriangleIndices.Length, data.materialRuns.Length);

            runTracker.EndRun(data.materialRuns, data.allTriangleIndices);

            //Process non collidable section
            for (int j = 0; j < nonCollidableQueue.Length; j++)
            {
                var item = nonCollidableQueue[j];
                AddMeshDataForVoxel(item.typeID, item.position, item.rotated, item.rotation);
            }

            runTracker.EndRun(data.materialRuns, data.allTriangleIndices);
        }
Пример #7
0
        private void AddFaceRotated(int meshID, float uvZ, int direction, int3 position, VoxelRotation rotation)
        {
            //Lighting
            Color vertexColourValue = new Color();

            if (data.includeLighting)
            {
                var directionVector = directionHelper.DirectionVectors[direction];
                var lightForFace    = GetLightValue(position + directionVector, data.lights, data.dimensions, data.neighbourData);
                vertexColourValue = lightForFace.ToVertexColour();
            }

            var meshRange = data.meshDatabase.meshTypeRanges[meshID];

            var usedNodesSlice = data.meshDatabase.nodesUsedByFaces[meshRange.start + direction];

            var currentIndex = data.vertices.Length;

            var rotationQuat = directionHelper.GetRotationQuat(rotation);

            //NOTE vertex definitions start from 0,0,0 in the bottom left of the cube, so an offset is needed for rotations
            float3 rotationOffset = new float3(.5f, .5f, .5f);

            //Add all the nodes used by this face
            for (int i = usedNodesSlice.start; i < usedNodesSlice.end; i++)
            {
                var node         = data.meshDatabase.allMeshNodes[i];
                var rotatedVert  = math.mul(rotationQuat, node.vertex - rotationOffset) + rotationOffset;
                var adjustedVert = rotatedVert + position;
                data.vertices.Add(adjustedVert);

                if (data.includeLighting)
                {
                    data.vertexColours.Add(vertexColourValue);
                }

                data.uvs.Add(new float3(node.uv, uvZ));
                var adjustedNorm = math.mul(rotationQuat, node.normal);
                data.normals.Add(adjustedNorm);
            }

            //Add the triangleIndices used by this face

            var relativeTrianglesSlice = data.meshDatabase.relativeTrianglesByFaces[meshRange.start + direction];


            for (int i = relativeTrianglesSlice.start; i < relativeTrianglesSlice.end; i++)
            {
                data.allTriangleIndices.Add(data.meshDatabase.allRelativeTriangles[i] + currentIndex);
            }
        }
Пример #8
0
        private FaceDescriptor makeFaceDescriptor(VoxelTypeID typeId, Direction originalDirection, LightValue lightValue, VoxelRotation rotation = default)
        {
            if (typeId == VoxelTypeID.AIR_ID)
            {
                return(nullFace);
            }

            var faceDirection = originalDirection;

            if (!rotation.isBlank)
            {
                ///Face direction needs to be the direction index of the face currently pointing in the original
                ///direction. Therefore it is the direction such that applying the rotation gives the original direction.
                faceDirection = directionRotator.GetDirectionBeforeRotation(originalDirection, rotation);
            }

            FaceDescriptor faceDescriptor = new FaceDescriptor()
            {
                typeId        = typeId,
                faceDirection = faceDirection,
                rotation      = rotation,
                lightValue    = lightValue
            };

            return(faceDescriptor);
        }
Пример #9
0
        private void Update()
        {
            if (UImanager.CursorInUseByUI)
            {
                return;//Don't run block placement logic when UI is using the cursor.
            }

            blockToPlace = hotbar.Selected;

            Ray ray = Camera.main.ViewportPointToRay(new Vector3(.5f, .5f, 0));
            //Ray ray = new Ray(transform.position, Camera.main.transform.forward);
            RaycastHit raycastHit;
            bool       hitAnything = Physics.Raycast(ray, out raycastHit, MaxPlacementDistance, LayerMask.GetMask("Voxels"));

            if (hitAnything)
            {
                Indicator.SetActive(true);
                Indicator.transform.position = WorldInterface.CenterOfVoxelAt(raycastHit.point + -0.1f * raycastHit.normal);
                Indicator.transform.rotation = Quaternion.Euler(0, 0, 0);

                LocationToPlaceBlock  = raycastHit.point + 0.1f * raycastHit.normal;
                LocationToDeleteBlock = raycastHit.point + -0.1f * raycastHit.normal;
            }
            else
            {
                Indicator.SetActive(false);
                return;
            }

            //Delete block
            if (Input.GetMouseButtonDown((int)BreakButton))
            {
                if (hitAnything)
                {
                    WorldInterface.RemoveVoxel(LocationToDeleteBlock);
                }
            }


            //Place block
            if (Input.GetMouseButtonDown((int)PlaceButton))
            {
                if (hitAnything)
                {
                    //Simple rotation calculation based on the normal of the face the player is looking at

                    rotationZ = Mathf.RoundToInt(Vector3.Dot(raycastHit.normal, Vector3.left));
                    if (rotationZ == -1)
                    {
                        rotationZ = 3;
                    }
                    rotationX = Mathf.RoundToInt(Vector3.Dot(raycastHit.normal, Vector3.forward));
                    if (rotationX == -1)
                    {
                        rotationX = 3;
                    }
                    rotationY = 0;

                    var rotation = new VoxelRotation()
                    {
                        x = rotationX, y = rotationY, z = rotationZ
                    };

                    if (blockToPlace.rotationConfiguration != null && blockToPlace.rotationConfiguration.RotationValid(rotation))
                    {
                        WorldInterface.PlaceVoxel(LocationToPlaceBlock, blockToPlace, rotation);
                    }
                    else
                    {
                        WorldInterface.PlaceVoxel(LocationToPlaceBlock, blockToPlace);
                    }
                }
            }

            if (Input.GetMouseButtonDown((int)PickButton))
            {
                if (hitAnything)
                {
                    if (WorldInterface.TryGetVoxelTypeAndID(LocationToDeleteBlock, out var voxelType, out var ID))
                    {
                        hotbar.SetCurrentItem(new InventoryItem()
                        {
                            ID = ID, typeDefinition = voxelType
                        });
                    }
                }
            }
        }