/// <summary> /// Create a new VoxelData /// </summary> /// <param name="id">The ID of the voxel data</param> /// <param name="name">The name of the voxel data</param> public VoxelData(VoxelDataID id, string name) { ID = id; VoxelName = name; Faces = new OrdinalBoolean(true); Solidity = new OrdinalBoolean(true); Textures = new VoxelDataTextures(0, 0); }
/// <summary> /// Add mesh data to the given mesh for a voxel in the given chunk at the given localPosition. Renders at the given position with the given size /// </summary> /// <param name="addToMeshData">The mesh to add the voxel to</param> /// <param name="chunk">The chunk the voxel is in</param> /// <param name="localPosition">The position in the chunk of the voxel</param> /// <param name="position">The position in the scene to render at</param> /// <param name="voxelSize">The size of the voxel</param> public override void AddMeshData(MeshData addToMeshData, Chunk chunk, IntVector3 localPosition, Vector3 position, float voxelSize) { // Ensure we have faces if (!VoxelData.Faces.HasAny) { return; } // Gather visibility data OrdinalBoolean visibility = new OrdinalBoolean(); visibility.IsUp = !chunk.IsSolid(localPosition.X, localPosition.Y + 1, localPosition.Z, OrdinalDirections.Down); visibility.IsDown = !chunk.IsSolid(localPosition.X, localPosition.Y - 1, localPosition.Z, OrdinalDirections.Up); visibility.IsNorth = !chunk.IsSolid(localPosition.X, localPosition.Y, localPosition.Z + 1, OrdinalDirections.South); visibility.IsSouth = !chunk.IsSolid(localPosition.X, localPosition.Y, localPosition.Z - 1, OrdinalDirections.North); visibility.IsEast = !chunk.IsSolid(localPosition.X + 1, localPosition.Y, localPosition.Z, OrdinalDirections.West); visibility.IsWest = !chunk.IsSolid(localPosition.X - 1, localPosition.Y, localPosition.Z, OrdinalDirections.East); // Create the actual data for the appropriate style switch (Style) { case VoxelStyle.Block: BlockMesher.CreateComplexBlockMeshData(addToMeshData, position, Orientation, Rotation, visibility, VoxelData, voxelSize); break; case VoxelStyle.Wedge: BlockMesher.CreateComplexWedgeMeshData(addToMeshData, position, Orientation, Rotation, visibility, VoxelData, voxelSize); break; case VoxelStyle.Corner: BlockMesher.CreateComplexCornerMeshData(addToMeshData, position, Orientation, Rotation, visibility, VoxelData, voxelSize); break; case VoxelStyle.InverseCorner: BlockMesher.CreateComplexInverseCornerMeshData(addToMeshData, position, Orientation, Rotation, visibility, VoxelData, voxelSize); break; default: BlockMesher.CreateSimpleBlockMeshData(addToMeshData, position, visibility, VoxelData, voxelSize); break; } }
/// <summary> /// Add mesh data to the given mesh for a voxel in the given chunk at the given localPosition. Renders at the given position with the given size /// </summary> /// <param name="addToMeshData">The mesh to add the voxel to</param> /// <param name="chunk">The chunk the voxel is in</param> /// <param name="localPosition">The position in the chunk of the voxel</param> /// <param name="position">The position in the scene to render at</param> /// <param name="voxelSize">The size of the voxel</param> public virtual void AddMeshData(MeshData addToMeshData, Chunk chunk, IntVector3 localPosition, Vector3 position, float voxelSize) { // Ensure we have faces if (!VoxelData.Faces.HasAny) { return; } // Gather visibility data OrdinalBoolean visibility = new OrdinalBoolean(); visibility.IsUp = !chunk.IsSolid(localPosition.X, localPosition.Y + 1, localPosition.Z, OrdinalDirections.Down); visibility.IsDown = !chunk.IsSolid(localPosition.X, localPosition.Y - 1, localPosition.Z, OrdinalDirections.Up); visibility.IsNorth = !chunk.IsSolid(localPosition.X, localPosition.Y, localPosition.Z + 1, OrdinalDirections.South); visibility.IsSouth = !chunk.IsSolid(localPosition.X, localPosition.Y, localPosition.Z - 1, OrdinalDirections.North); visibility.IsEast = !chunk.IsSolid(localPosition.X + 1, localPosition.Y, localPosition.Z, OrdinalDirections.West); visibility.IsWest = !chunk.IsSolid(localPosition.X - 1, localPosition.Y, localPosition.Z, OrdinalDirections.East); // Create the actual data BlockMesher.CreateSimpleBlockMeshData(addToMeshData, position, visibility, VoxelData, voxelSize); }
/// <summary> /// Set the solidity data for the voxel data /// </summary> /// <param name="solidity">The new solidity data</param> /// <returns></returns> public VoxelData SetSolidity(OrdinalBoolean solidity) { Solidity = solidity; return(this); }
/// <summary> /// Set the solidity data for the voxel data /// </summary> /// <param name="solidity">The new solidity value for all faces</param> /// <returns></returns> public VoxelData SetSolidity(bool solidity) { Solidity = new OrdinalBoolean(solidity); return(this); }
/// <summary> /// Set the face data for the voxel data /// </summary> /// <param name="faces">The new face data</param> /// <returns></returns> public VoxelData SetFaces(OrdinalBoolean faces) { Faces = faces; return(this); }
/// <summary> /// Set the face data for the voxel data /// </summary> /// <param name="hasFaces">The new face value for all faces</param> /// <returns></returns> public VoxelData SetFaces(bool hasFaces) { Faces = new OrdinalBoolean(hasFaces); return(this); }
/// <summary> /// Create a complex inverse corner with orientation and rotation /// </summary> /// <param name="addToMeshData">The mesh data to add the block to</param> /// <param name="position">The position of the block</param> /// <param name="orientation">The voxel's orientation</param> /// <param name="rotAmount">The voxel's rotation around the orientation axis (0, 90, 180, 270)</param> /// <param name="visibility">Which sides of the block are visible</param> /// <param name="voxelData">The type of voxel to render</param> /// <param name="voxelSize">The size of the voxel</param> public static void CreateComplexInverseCornerMeshData(MeshData addToMeshData, Vector3 position, OrdinalDirections orientation, int rotAmount, OrdinalBoolean visibility, VoxelData voxelData, float voxelSize) { // TODO: Implement this method }
/// <summary> /// Create a complex wedge with orientation and rotation /// </summary> /// <param name="addToMeshData">The mesh data to add the block to</param> /// <param name="position">The position of the block</param> /// <param name="orientation">The voxel's orientation</param> /// <param name="rotAmount">The voxel's rotation around the orientation axis (0, 90, 180, 270)</param> /// <param name="visibility">Which sides of the block are visible</param> /// <param name="voxelData">The type of voxel to render</param> /// <param name="voxelSize">The size of the voxel</param> public static void CreateComplexWedgeMeshData(MeshData addToMeshData, Vector3 position, OrdinalDirections orientation, int rotAmount, OrdinalBoolean visibility, VoxelData voxelData, float voxelSize) { // Vertices int[] comps; Vector3 v1, v2, v3, v4; // UVs Vector2 uvC; Vector2[] uvs = new Vector2[4]; float rot; // General bool slopeDone = false; OrdinalDirections dirGlob; OrdinalDirections dirLoc; for (int i = 0; i < 6; i++) { dirGlob = (OrdinalDirections)i; if (visibility.GetBoolForDir(dirGlob) && voxelData.Faces.GetBoolForDir(dirLoc = OrdinalDirectionsHelper.GlobalToLocalDirection(dirGlob, orientation, rotAmount))) { // Slope if (!slopeDone && (dirLoc == OrdinalDirections.Up || dirLoc == OrdinalDirections.North || dirLoc == OrdinalDirections.East || dirLoc == OrdinalDirections.West)) { comps = WEDGE_MESH_MAP[(int)orientation, rotAmount / 90, (int)orientation]; // UVs rot = OrdinalDirectionsHelper.DirectionToRotation(OrdinalDirections.Up, orientation, rotAmount); uvs[0] = new Vector2(voxelData.Textures.GetX(OrdinalDirections.Up), voxelData.Textures.GetY(OrdinalDirections.Up)) * VoxelDataTextures.UV_SIZE_WITH_PADDING + VoxelDataTextures.TEXTURE_PADDING_OFFSET; uvs[1] = uvs[0] + new Vector2(0, VoxelDataTextures.TEXTURE_DIMENSION); uvs[2] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, VoxelDataTextures.TEXTURE_DIMENSION); uvs[3] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, 0); // Average UV Pos uvC = new Vector2((uvs[0].x + uvs[1].x + uvs[2].x + uvs[3].x) / 4, (uvs[0].y + uvs[1].y + uvs[2].y + uvs[3].y) / 4); // UV Rotation uvs[0] = (uvs[0] - uvC).Rotate(rot) + uvC; uvs[1] = (uvs[1] - uvC).Rotate(rot) + uvC; uvs[2] = (uvs[2] - uvC).Rotate(rot) + uvC; uvs[3] = (uvs[3] - uvC).Rotate(rot) + uvC; v1 = new Vector3(comps[0], comps[1], comps[2]) * voxelSize + position; v2 = new Vector3(comps[3], comps[4], comps[5]) * voxelSize + position; v3 = new Vector3(comps[6], comps[7], comps[8]) * voxelSize + position; v4 = new Vector3(comps[9], comps[10], comps[11]) * voxelSize + position; // Mesh Data addToMeshData.AddQuad(v1, v2, v3, v4, 0); // Collider Data addToMeshData.AddQuadToCollider(v1, v2, v3, v4); // UVs addToMeshData.AddUV(uvs[comps[12]]); addToMeshData.AddUV(uvs[comps[13]]); addToMeshData.AddUV(uvs[comps[14]]); addToMeshData.AddUV(uvs[comps[15]]); // Only render the top once slopeDone = true; } // Quad Faces if (dirLoc == OrdinalDirections.South || dirLoc == OrdinalDirections.Down) { comps = WEDGE_MESH_MAP[(int)orientation, rotAmount / 90, (int)dirGlob]; // UVs rot = OrdinalDirectionsHelper.DirectionToRotation(dirGlob, orientation, rotAmount); uvs[0] = new Vector2(voxelData.Textures.GetX(dirLoc), voxelData.Textures.GetY(dirLoc)) * VoxelDataTextures.UV_SIZE_WITH_PADDING + VoxelDataTextures.TEXTURE_PADDING_OFFSET; uvs[1] = uvs[0] + new Vector2(0, VoxelDataTextures.TEXTURE_DIMENSION); uvs[2] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, VoxelDataTextures.TEXTURE_DIMENSION); uvs[3] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, 0); // Average UV Pos uvC = new Vector2((uvs[0].x + uvs[1].x + uvs[2].x + uvs[3].x) / 4, (uvs[0].y + uvs[1].y + uvs[2].y + uvs[3].y) / 4); // UV Rotation uvs[0] = (uvs[0] - uvC).Rotate(rot) + uvC; uvs[1] = (uvs[1] - uvC).Rotate(rot) + uvC; uvs[2] = (uvs[2] - uvC).Rotate(rot) + uvC; uvs[3] = (uvs[3] - uvC).Rotate(rot) + uvC; v1 = new Vector3(comps[0], comps[1], comps[2]) * voxelSize + position; v2 = new Vector3(comps[3], comps[4], comps[5]) * voxelSize + position; v3 = new Vector3(comps[6], comps[7], comps[8]) * voxelSize + position; v4 = new Vector3(comps[9], comps[10], comps[11]) * voxelSize + position; // Mesh Data addToMeshData.AddQuad(v1, v2, v3, v4, 0); // Collider Data addToMeshData.AddQuadToCollider(v1, v2, v3, v4); // UVs addToMeshData.AddUV(uvs[comps[12]]); addToMeshData.AddUV(uvs[comps[13]]); addToMeshData.AddUV(uvs[comps[14]]); addToMeshData.AddUV(uvs[comps[15]]); } // Triangle Faces else if (dirLoc == OrdinalDirections.East || dirLoc == OrdinalDirections.West) { comps = WEDGE_MESH_MAP[(int)orientation, rotAmount / 90, (int)dirGlob]; // UVs rot = OrdinalDirectionsHelper.DirectionToRotation(dirGlob, orientation, rotAmount); uvs[0] = new Vector2(voxelData.Textures.GetX(dirLoc), voxelData.Textures.GetY(dirLoc)) * VoxelDataTextures.UV_SIZE_WITH_PADDING + VoxelDataTextures.TEXTURE_PADDING_OFFSET; uvs[1] = uvs[0] + new Vector2(0, VoxelDataTextures.TEXTURE_DIMENSION); uvs[2] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, VoxelDataTextures.TEXTURE_DIMENSION); uvs[3] = uvs[0] + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, 0); // Average UV Pos uvC = new Vector2((uvs[0].x + uvs[1].x + uvs[2].x + uvs[3].x) / 4, (uvs[0].y + uvs[1].y + uvs[2].y + uvs[3].y) / 4); // UV Rotation uvs[0] = (uvs[0] - uvC).Rotate(rot) + uvC; uvs[1] = (uvs[1] - uvC).Rotate(rot) + uvC; uvs[2] = (uvs[2] - uvC).Rotate(rot) + uvC; uvs[3] = (uvs[3] - uvC).Rotate(rot) + uvC; v1 = new Vector3(comps[0], comps[1], comps[2]) * voxelSize + position; v2 = new Vector3(comps[3], comps[4], comps[5]) * voxelSize + position; v3 = new Vector3(comps[6], comps[7], comps[8]) * voxelSize + position; // Mesh Data addToMeshData.AddTriangle(v1, v2, v3, 0); // Collider Data addToMeshData.AddTriangleToCollider(v1, v2, v3); // UVs addToMeshData.AddUV(uvs[comps[9]]); addToMeshData.AddUV(uvs[comps[10]]); addToMeshData.AddUV(uvs[comps[11]]); } } } }
/// <summary> /// Create a complex block with orientation and rotation /// </summary> /// <param name="addToMeshData">The mesh data to add the block to</param> /// <param name="position">The position of the block</param> /// <param name="orientation">The voxel's orientation</param> /// <param name="rotAmount">The voxel's rotation around the orientation axis (0, 90, 180, 270)</param> /// <param name="visibility">Which sides of the block are visible</param> /// <param name="voxelData">The type of voxel to render</param> /// <param name="voxelSize">The size of the voxel</param> public static void CreateComplexBlockMeshData(MeshData addToMeshData, Vector3 position, OrdinalDirections orientation, int rotAmount, OrdinalBoolean visibility, VoxelData voxelData, float voxelSize) { float rot; Vector2 uvC, uv1, uv2, uv3, uv4; OrdinalDirections dirGlob; OrdinalDirections dirLoc; for (int i = 0; i < 6; i++) { dirGlob = (OrdinalDirections)i; // Check if the side is visible and the localized face is actually a face if (visibility.GetBoolForDir(dirGlob) && voxelData.Faces.GetBoolForDir(dirLoc = OrdinalDirectionsHelper.GlobalToLocalDirection(dirGlob, orientation, rotAmount))) { rot = OrdinalDirectionsHelper.DirectionToRotation(dirGlob, orientation, rotAmount); // Mesh Data addToMeshData.AddQuad(position, dirGlob, voxelSize, 0); // Collider Data addToMeshData.AddQuadToCollider(position, dirGlob, voxelSize); // UVs uv1 = new Vector2(voxelData.Textures.GetX(dirLoc), voxelData.Textures.GetY(dirLoc)) * VoxelDataTextures.UV_SIZE_WITH_PADDING + VoxelDataTextures.TEXTURE_PADDING_OFFSET; uv2 = uv1 + new Vector2(0, VoxelDataTextures.TEXTURE_DIMENSION); uv3 = uv1 + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, VoxelDataTextures.TEXTURE_DIMENSION); uv4 = uv1 + new Vector2(VoxelDataTextures.TEXTURE_DIMENSION, 0); // Average UV Pos uvC = new Vector2((uv1.x + uv2.x + uv3.x + uv4.x) / 4, (uv1.y + uv2.y + uv3.y + uv4.y) / 4); // UV Rotation uv1 = (uv1 - uvC).Rotate(rot) + uvC; uv2 = (uv2 - uvC).Rotate(rot) + uvC; uv3 = (uv3 - uvC).Rotate(rot) + uvC; uv4 = (uv4 - uvC).Rotate(rot) + uvC; // UVs addToMeshData.AddUV(uv1); addToMeshData.AddUV(uv2); addToMeshData.AddUV(uv3); addToMeshData.AddUV(uv4); } } }
/// <summary> /// Create a simple block /// </summary> /// <param name="addToMeshData">The mesh data to add the block to</param> /// <param name="position">The position of the block</param> /// <param name="visibility">Which sides of the block are visible</param> /// <param name="voxelData">The type of voxel to render</param> /// <param name="voxelSize">The size of the voxel</param> public static void CreateSimpleBlockMeshData(MeshData addToMeshData, Vector3 position, OrdinalBoolean visibility, VoxelData voxelData, float voxelSize) { OrdinalDirections dir; for (int i = 0; i < 6; i++) { dir = (OrdinalDirections)i; // Check if the side is visible and has a face if (visibility.GetBoolForDir(dir) && voxelData.Faces.GetBoolForDir(dir)) { // Mesh Data addToMeshData.AddQuad(position, dir, voxelSize, 0); // Collider Data addToMeshData.AddQuadToCollider(position, dir, voxelSize); // UVs addToMeshData.AddQuadUVs(new Rect( new Vector2(voxelData.Textures.GetX(dir), voxelData.Textures.GetY(dir)) * VoxelDataTextures.UV_SIZE_WITH_PADDING + VoxelDataTextures.TEXTURE_PADDING_OFFSET, VoxelDataTextures.TEXTURE_SIZE), dir); } } }