void CreateVoxelAtPos(Vector3Int pos) { for (int i = 0; i < 6; i++) { if (ShouldRenderFace(pos + VoxelFaceData.faceChecks[i])) { VoxelState voxelState = voxelMap[pos.x, pos.y, pos.z]; vertices.Add(pos + VoxelRenderData.voxelVertices[VoxelRenderData.voxelTriangles[i, 0]]); vertices.Add(pos + VoxelRenderData.voxelVertices[VoxelRenderData.voxelTriangles[i, 1]]); vertices.Add(pos + VoxelRenderData.voxelVertices[VoxelRenderData.voxelTriangles[i, 2]]); vertices.Add(pos + VoxelRenderData.voxelVertices[VoxelRenderData.voxelTriangles[i, 3]]); AddTexture(world.voxelTypes[voxelState.id].GetTextureID(i)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 3); vertexIndex += 4; } } }
public void ModifyVoxel(Vector4Int pos, byte id) { VoxelState voxel = getVoxel(pos); if (voxel.blockID == id) { return; } BlockType new_voxel = World.Instance.blockTypes[id]; // Cache old opacity byte oldOpacity = voxel.properties.opacity; voxel.blockID = id; if (voxel.properties.opacity != oldOpacity && (pos.y == ChunkData.cHeight - 1 || getVoxel(pos + Vector4Int.up).light == 15)) { Lighting.CastNaturalLight(this, pos); } World.Instance.worldData.AddToModifieds(this); if (chunk != null) { World.Instance.AddChunkToUpdate(chunk); } }
public static void CastNaturalLight(ChunkData chunkData, int x, int z, int startY) { if (startY > VoxelData.ChunkHeight - 1) { startY = VoxelData.ChunkHeight - 1; Debug.LogWarning("Attempted to cast natural light from above world."); } bool obstructed = false; for (int y = startY; y > -1; y--) { VoxelState voxel = chunkData.map[x, y, z]; if (obstructed) { voxel.light = 0; } else if (voxel.properties.opacity > 0) { voxel.light = 0; obstructed = true; } else { voxel.light = 15; } } }
static VoxelState GetSHNearest(ProbeVolume volume, Vector3 worldPosition, ref float[] shData) { int voxelIndex = volume.Grid.GetVoxelIndex(worldPosition); if (voxelIndex < 0) { return(VoxelState.Empty); } VoxelState voxelState = GetVoxelState(volume, voxelIndex); if (voxelState != VoxelState.Valid) { return(voxelState); } int nearestIndex = volume.Grid.GetNearestLocalProbeIndex(worldPosition, voxelIndex); if (nearestIndex >= 0) { uint dataIndex = volume.IndexBuffer.GetSHDataIndex(nearestIndex, 0); bool isValid = volume.IndexBuffer.IsIndexValueValid(dataIndex); if (isValid) { shData = volume.DataBuffer.GetSHData((int)dataIndex); return(VoxelState.Valid); } } return(VoxelState.Empty); }
public void Populate() { for (int y = 0; y < VoxelData.ChunkHeight; y++) { for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { Vector3 voxelGlobalPos = new Vector3(x + position.x, y, z + position.y); map[x, y, z] = new VoxelState(World.Instance.GetVoxel(voxelGlobalPos), this, new Vector3Int(x, y, z)); for (int p = 0; p < 6; p++) { Vector3Int neighbourV3 = new Vector3Int(x, y, z) + VoxelData.faceChecks[p]; if (IsVoxelInChunk(neighbourV3)) { map[x, y, z].neighbours[p] = VoxelFromV3Int(neighbourV3); } else { map[x, y, z].neighbours[p] = World.Instance.worldData.GetVoxel(voxelGlobalPos + VoxelData.faceChecks[p]); } } } } } Lighting.RecalculateNaturalLight(this); World.Instance.worldData.AddToModifiedChunkList(this); }
public void ModifyVoxel(Vector3Int pos, byte _id) { // If we've somehow tried to change a block for the same block, just return. if (map[pos.x, pos.y, pos.z].id == _id) { return; } // Cache voxels for easier code. VoxelState voxel = map[pos.x, pos.y, pos.z]; BlockType newVoxel = World.Instance.blocktypes[_id]; // Cache the old opacity value. byte oldOpacity = voxel.properties.opacity; // Set voxel to new ID. voxel.id = _id; // If the opacity values of the voxel have changed and the voxel above is in direct sunlight // (or is above the world) recast light from that voxel downwards. if (voxel.properties.opacity != oldOpacity && (pos.y == VoxelData.ChunkHeight - 1 || map[pos.x, pos.y + 1, pos.z].light == 15)) { Lighting.CastNaturalLight(this, pos.x, pos.z, pos.y + 1); } // Add this ChunkData to the modified chunks list. World.Instance.worldData.AddToModifiedChunkList(this); // If we have a chunk attached, add that for updating. if (chunk != null) { World.Instance.AddChunkToUpdate(chunk); } }
static VoxelState GetSHTriLinear(ProbeVolume v, Vector3 worldPosition, ref float[] shData) { int voxelIndex = v.Grid.GetVoxelIndex(worldPosition); if (voxelIndex < 0) { return(VoxelState.Empty); } VoxelState voxelState = GetVoxelState(v, voxelIndex); if (voxelState != VoxelState.Valid) { return(VoxelState.Empty); } float[] weights = v.Grid.GetVoxelTriLinearWeight(worldPosition, voxelIndex); //Blend 4 regions var lerp1 = GetLerp(weights[0], v.GetSHData(voxelIndex, 0), v.GetSHData(voxelIndex, 1)); var lerp2 = GetLerp(weights[0], v.GetSHData(voxelIndex, 4), v.GetSHData(voxelIndex, 5)); var leftBlend = GetLerp(weights[1], lerp1, lerp2); //Blend 4 regions var lerp3 = GetLerp(weights[0], v.GetSHData(voxelIndex, 2), v.GetSHData(voxelIndex, 3)); var lerp4 = GetLerp(weights[0], v.GetSHData(voxelIndex, 6), v.GetSHData(voxelIndex, 7)); var rightBlend = GetLerp(weights[1], lerp3, lerp4); //Blend the 2 outputs into a final output var finalBlend = GetLerp(weights[2], leftBlend, rightBlend); shData = v.GetSHData(voxelIndex, 0); return(VoxelState.Valid); }
public void ModifyVoxel(Vector3Int pos, byte _id) { if (map[pos.x, pos.y, pos.z].id == _id) { return; } VoxelState voxel = map[pos.x, pos.y, pos.z]; BlockType newVoxel = World.Instance.blockTypes[_id]; byte oldOpacity = voxel.properties.opacity; voxel.id = _id; if (voxel.properties.opacity != oldOpacity && (pos.y == VoxelData.ChunkHeight - 1 || map[pos.x, pos.y, pos.z].light == 15)) { Lighting.CastNaturalLight(this, pos.x, pos.z, pos.y + 1); } World.Instance.worldData.AddToModifiedChunkList(this); if (chunk != null) { World.Instance.AddChunkToUpdate(chunk); } }
public void Populate() { for (int y = 0; y < VoxelData.chunkHeight; y++) { for (int x = 0; x < VoxelData.chunkWidth; x++) { for (int z = 0; z < VoxelData.chunkWidth; z++) { Vector3 globalVoxelPos = new Vector3(x + position.x, y, z + position.y); map[x, y, z] = new VoxelState(World.Instance.GetVoxel(globalVoxelPos), this, new Vector3Int(x, y, z)); //loop through voxel's neighbour and try to set them for (int i = 0; i < 6; i++) { Vector3Int neighbourVector = new Vector3Int(x, y, z) + VoxelData.adjFaceChecks[i]; if (IsVoxelInChunk(neighbourVector)) { map[x, y, z].neighbours[i] = VoxelFromPosition(neighbourVector); } else { map[x, y, z].neighbours[i] = World.Instance.worldData.GetVoxel(globalVoxelPos + VoxelData.adjFaceChecks[i]); } } } } } Lighting.RecalculateNaturalLight(this); World.Instance.worldData.AddModifiedChunk(this); }
void PopulateVoxelMap() { for (int y = 0; y < VoxelData.ChunkHeight; y++) { for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { voxelMap[x, y, z] = new VoxelState(world.GetVoxel(new Vector3(x, y, z) + position)); } } } isVoxelMapPopulated = true; lock (world.ChunkUpdateThreadLock) { world.chunksToUpdate.Add(this); } if (world.settings.enableAnimatedChunks) { chunkObject.AddComponent <ChunkLoadAnimation>(); } }
public void Populate() { for (int y = 0; y < VoxelData.ChunkHeight; y++) { for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { Vector3 voxelGlobalPos = new Vector3(x + position.x, y, z + position.y); map[x, y, z] = new VoxelState(World.Instance.GetVoxel(voxelGlobalPos), this, new Vector3Int(x, y, z)); // Loop through each of the voxels neighbours and attempt to set them. for (int p = 0; p < 6; p++) { Vector3Int neighbourV3 = new Vector3Int(x, y, z) + VoxelData.faceChecks[p]; if (IsVoxelInChunk(neighbourV3)) // If in chunk, get voxel straight from map. { map[x, y, z].neighbours[p] = VoxelFromV3Int(neighbourV3); } else // Else see if we can get the neighbour from WorldData. { map[x, y, z].neighbours[p] = World.Instance.worldData.GetVoxel(voxelGlobalPos + VoxelData.faceChecks[p]); } } } } } Lighting.RecalculateNaturaLight(this); World.Instance.worldData.AddToModifiedChunkList(this); }
public static void NaturalLight(ChunkData chunk, int x, int z, int startY) { if (startY > VoxelData.chunkHeight - 1) { startY = VoxelData.chunkHeight - 1; } //check if light has hit an opaque or translucent block bool lightObstructed = false; for (int y = startY; y > -1; y--) { VoxelState voxel = chunk.map[x, y, z]; if (lightObstructed) { voxel.light = 0; } else if (voxel.properties.opacity > 0) { voxel.light = 0; lightObstructed = true; } else { voxel.light = 15; } } }
void UpdateMeshData(Vector3 pos) { int x = Mathf.FloorToInt(pos.x); int y = Mathf.FloorToInt(pos.y); int z = Mathf.FloorToInt(pos.z); byte blockID = voxelMap[x, y, z].id; // bool isTransparent = world.blocktypes[blockID].renderNeighborFaces; for (int p = 0; p < 6; p++) { VoxelState neighbor = CheckVoxel(pos + VoxelData.faceChecks[p]); if (neighbor != null && world.blocktypes[neighbor.id].renderNeighborFaces) { vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 0]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 1]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 2]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 3]]); for (int i = 0; i < 4; i++) { normals.Add(VoxelData.faceChecks[p]); } AddTexture(world.blocktypes[blockID].GetTextureID(p)); float lightLevel = neighbor.globalLightPercent; colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); if (!world.blocktypes[neighbor.id].renderNeighborFaces) { triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 3); } else { transparentTriangles.Add(vertexIndex); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 3); } vertexIndex += 4; } } }
public void AddActiveVoxel(VoxelState voxel) { if (!activeVoxels.Contains(voxel)) // Make sure voxel isn't already in list. { activeVoxels.Add(voxel); } }
void UpdateMeshData(Vector3 pos) { int x = Mathf.FloorToInt(pos.x); int y = Mathf.FloorToInt(pos.y); int z = Mathf.FloorToInt(pos.z); byte blockID = voxelMap[x, y, z].id; //bool isTransparent = world.blockTypes[blockID].renderNeighborFaces; for (int p = 0; p < 6; p++) { VoxelState neighbor = CheckVoxel(pos + VoxelData.faceChecks[p]); if (neighbor != null && world.blockTypes[neighbor.id].renderNeighborFaces) { vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 0]]); vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 1]]); vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 2]]); vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 3]]); AddTexture(world.blockTypes[blockID].GetTextureID(p)); float lightLevel = neighbor.globalLightPercent; colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); // Triangles add sequence is based on pattern found in between short and long versions of VoxelData.voxelTris /*if (!isTransparent) * {*/ triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 3); /*} * else * { * transparentTriangles.Add(vertexIndex); * transparentTriangles.Add(vertexIndex + 1); * transparentTriangles.Add(vertexIndex + 2); * transparentTriangles.Add(vertexIndex + 2); * transparentTriangles.Add(vertexIndex + 1); * transparentTriangles.Add(vertexIndex + 3); * }*/ vertexIndex += 4; } } }
public VoxelState(VoxelState voxel, ChunkData chunk) { blockID = voxel.blockID; position = voxel.position; neighbors = new VoxelNeighbors(this); chunkData = chunk; light = 0; }
void UpdateMeshData(Vector3 pos) { int x = Mathf.FloorToInt(pos.x); int y = Mathf.FloorToInt(pos.y); int z = Mathf.FloorToInt(pos.z); VoxelState voxel = chunkData.map[x, y, z]; for (int p = 0; p < 6; p++) { VoxelState neighbor = chunkData.map[x, y, z].neighbours[p]; if (neighbor != null && World.Instance.blocktypes[neighbor.id].renderNeighborFaces) { vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 0]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 1]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 2]]); vertices.Add(pos + VoxelData.voxelVerts [VoxelData.voxelTris [p, 3]]); for (int i = 0; i < 4; i++) { normals.Add(VoxelData.faceChecks[p]); } AddTexture(voxel.properties.GetTextureID(p)); float lightLevel = neighbor.lightAsFloat; colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); colors.Add(new Color(0, 0, 0, lightLevel)); if (!neighbor.properties.renderNeighborFaces) { triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 3); } else { transparentTriangles.Add(vertexIndex); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 3); } vertexIndex += 4; } } }
void CalculateLight() { Queue <Vector3Int> litVoxels = new Queue <Vector3Int>(); for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { // Percentage of global illumination amount. float lightRay = 1f; for (int y = VoxelData.ChunkHeight - 1; y >= 0; y--) { VoxelState thisVoxel = chunkData.map[x, y, z]; if (thisVoxel.id > 0 && World.Instance.blocktypes[thisVoxel.id].transparency < lightRay) { lightRay = World.Instance.blocktypes[thisVoxel.id].transparency; } thisVoxel.globalLightPercent = lightRay; chunkData.map[x, y, z] = thisVoxel; if (lightRay > VoxelData.lightFalloff) { litVoxels.Enqueue(new Vector3Int(x, y, z)); } } } } // Affect neighbouring blocks' light levels. while (litVoxels.Count > 0) { Vector3Int v = litVoxels.Dequeue(); for (int p = 0; p < 6; p++) { Vector3 currentVoxel = v + VoxelData.faceChecks[p]; Vector3Int neighbour = new Vector3Int((int)currentVoxel.x, (int)currentVoxel.y, (int)currentVoxel.z); // If it's inside the chunk we're working on currently if (IsVoxelInChunk(neighbour.x, neighbour.y, neighbour.z)) { if (chunkData.map[neighbour.x, neighbour.y, neighbour.z].globalLightPercent < chunkData.map[v.x, v.y, v.z].globalLightPercent - VoxelData.lightFalloff) { chunkData.map[neighbour.x, neighbour.y, neighbour.z].globalLightPercent = chunkData.map[v.x, v.y, v.z].globalLightPercent - VoxelData.lightFalloff; if (chunkData.map[neighbour.x, neighbour.y, neighbour.z].globalLightPercent > VoxelData.lightFalloff) { litVoxels.Enqueue(neighbour); } } } } } }
// 計算亮度 public void CalculateLight() { Queue <Vector3s> litVoxels = new Queue <Vector3s>(); for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { float lightRay = 1f; for (int y = VoxelData.ChunkHeight - 1; y > -1; y--) { VoxelState thisVoxel = voxelMap[x, y, z]; if (thisVoxel.id > 0 && world.blocks[(int)thisVoxel.id].transparency < lightRay) { lightRay = world.blocks[(int)thisVoxel.id].transparency; } thisVoxel.globalLightPercent = lightRay; voxelMap[x, y, z] = thisVoxel; if (lightRay > VoxelData.lightFalloff) { litVoxels.Enqueue(new Vector3s(x, y, z)); } } } } while (litVoxels.Count > 0) { Vector3s v = litVoxels.Dequeue(); for (int p = 0; p < 6; p++) { Vector3s currentVoxel = v + VoxelData.faceChecks[p]; int xCheck = (int)currentVoxel.x; int yCheck = (int)currentVoxel.y; int zCheck = (int)currentVoxel.z; Vector3s neighbor = new Vector3s(currentVoxel.x, currentVoxel.y, currentVoxel.z); if (IsVoxelInChunk(xCheck, yCheck, zCheck)) { if (voxelMap[xCheck, yCheck, zCheck].globalLightPercent < voxelMap[(int)v.x, (int)v.y, (int)v.z].globalLightPercent - VoxelData.lightFalloff) { voxelMap[xCheck, yCheck, zCheck].globalLightPercent = voxelMap[(int)v.x, (int)v.y, (int)v.z].globalLightPercent - VoxelData.lightFalloff; if (voxelMap[xCheck, yCheck, zCheck].globalLightPercent > VoxelData.lightFalloff) { litVoxels.Enqueue(neighbor); } } } } } }
/// <summary> /// Voxel constructor. Will construct a voxel object and a Gameobject linked to this to the voxelgrid. /// </summary> /// <param name="index">index of the voxel</param> /// <param name="goVoxel">prefab of the voxel gameobject</param> public Voxel(Vector3Int index, GameObject goVoxel, VoxelGrid grid) { _grid = grid; Index = index; _goVoxel = GameObject.Instantiate(goVoxel, Centre, Quaternion.identity); _goVoxel.GetComponent <VoxelTrigger>().TriggerVoxel = this; _goVoxel.transform.localScale = Vector3.one * _grid.VoxelSize * 0.95f; Status = VoxelState.Available; }
public bool SetVoxel(Point3 point, string stateName) { VoxelState state = GetState(stateName); Voxel v = GetVoxelAt(point); if (v == null) { Debug.Log("Out of bounds: " + point.ToString() + " " + stateName); if (stateName == "Snake") { // ded _ctrl.GameOver(); running = false; } else { Debug.LogError("Invalid voxelsetting!"); } return(false); } if (stateName == "Snake") { // check to see if there's anything in the snakes way if (v.State.name == "Goal") { // grow + seed new goal score += 1; _snake.snakeLength += growthRate; goalCount -= 1; _ctrl.PlayGrabTone(); NewGoal(); } else if (v.State.name == "Snake") { // collided with self :( _ctrl.GameOver(); running = false; return(false); } } v.State = state; if (stateName == "Empty") { _XVoxelPlanes[v.point.x].Remove(v); _YVoxelPlanes[v.point.y].Remove(v); } else { _XVoxelPlanes[v.point.x].Add(v); _YVoxelPlanes[v.point.y].Add(v); } return(true); }
public bool CheckForVoxel(Vector3 pos) { VoxelState voxel = worldData.GetVoxel(pos); if (blockTypes[voxel.id].isSolid) { return(true); } return(false); }
void CalculateLight() { Queue <Vector3Int> litVoxels = new Queue <Vector3Int>(); for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { float lightRay = 1f; for (int y = VoxelData.ChunkHeight - 1; y >= 0; y--) { VoxelState thisVoxel = (voxelMap[x, y, z]); if (thisVoxel.id > 0 && world.blockTypes[thisVoxel.id].transparency < lightRay) { lightRay = world.blockTypes[thisVoxel.id].transparency; } thisVoxel.globalLightPercent = lightRay; voxelMap[x, y, z] = thisVoxel; if (lightRay > VoxelData.lightFalloff) { litVoxels.Enqueue(new Vector3Int(x, y, z)); } } } } while (litVoxels.Count > 0) { Vector3Int v = litVoxels.Dequeue(); for (int p = 0; p < 6; p++) { Vector3 currentVoxel = v + VoxelData.faceChecks[p]; Vector3Int neighbor = new Vector3Int((int)currentVoxel.x, (int)currentVoxel.y, (int)currentVoxel.z); if (IsVoxelInChunk(neighbor.x, neighbor.y, neighbor.z)) { if (voxelMap[neighbor.x, neighbor.y, neighbor.z].globalLightPercent < voxelMap[v.x, v.y, v.z].globalLightPercent - VoxelData.lightFalloff) { voxelMap[neighbor.x, neighbor.y, neighbor.z].globalLightPercent = voxelMap[v.x, v.y, v.z].globalLightPercent - VoxelData.lightFalloff; if (voxelMap[neighbor.x, neighbor.y, neighbor.z].globalLightPercent > VoxelData.lightFalloff) { litVoxels.Enqueue(neighbor); } } } } } }
private void CalculateLight() { Queue <Vector3Int> litVoxels = new Queue <Vector3Int>(); for (int x = 0; x < VoxelData.ChunkSize.x; x++) { for (int z = 0; z < VoxelData.ChunkSize.z; z++) { float lightRay = 1; for (int y = VoxelData.ChunkSize.y - 1; y >= 0; y--) { VoxelState thisVoxel = voxelMaps[x, y, z]; if (thisVoxel.id > 0 && blockDatabase.blockDatabase[thisVoxel.id].transparency < lightRay) { lightRay = blockDatabase.blockDatabase[thisVoxel.id].transparency; } thisVoxel.globalLightPercent = lightRay; voxelMaps[x, y, z] = thisVoxel; if (lightRay > VoxelData.lightFalloff) { litVoxels.Enqueue(new Vector3Int(x, y, z)); } } } } while (litVoxels.Count > 0) { Vector3Int voxel = litVoxels.Dequeue(); for (int p = 0; p < 6; p++) { Vector3 currentVoxel = voxel + VoxelData.faceChecks[p]; Vector3Int neighbor = new Vector3Int((int)currentVoxel.x, (int)currentVoxel.y, (int)currentVoxel.z); if (IsVoxelInChunk(new int3(neighbor.x, neighbor.y, neighbor.z))) { if (voxelMaps[neighbor.x, neighbor.y, neighbor.z].globalLightPercent < voxelMaps[voxel.x, voxel.y, voxel.z].globalLightPercent - VoxelData.lightFalloff) { voxelMaps[neighbor.x, neighbor.y, neighbor.z].globalLightPercent = voxelMaps[voxel.x, voxel.y, voxel.z].globalLightPercent - VoxelData.lightFalloff; if (voxelMaps[neighbor.x, neighbor.y, neighbor.z].globalLightPercent > VoxelData.lightFalloff) { litVoxels.Enqueue(neighbor); } } } } } }
public void RemoveActiveVoxel(VoxelState voxel) { for (int i = 0; i < activeVoxels.Count; i++) { if (activeVoxels[i] == voxel) { activeVoxels.RemoveAt(i); return; } } }
public VoxelState setVoxel(int x, int y, int z, int w, VoxelState voxel) { if (x < 0 || x >= cWidth || y < 0 || y >= cHeight || z < 0 || z >= cLength || w < 0 || w >= cDepth) { return(null); } return(map[x, y, z, w] = voxel); }
/// <summary> /// Attempts to set a voxel's state within this frame, at a specified x,y,z array position /// </summary> /// <param name="x">X array position</param> /// <param name="y">Y array position</param> /// <param name="z">Z array position</param> /// <param name="state">The new voxel state to set to</param> public void SetVoxelStateAtArrayPosition(int x, int y, int z, VoxelState state) { if (x < 0 || y < 0 || z < 0 || x >= XSize || y >= YSize || z >= ZSize) { return; } bool updateVox = false; int index = x + XSize * (y + YSize * z); if (state != Voxels[index].State) { updateVox = true; } Voxels[index].State = state; if (!updateVox) { return; } if (chunks == null) { GetChunkReferences(); } AddChunkToUpdateList(x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize); // If we're at the edge of a chunk, we should update the next voxel as well if (x % ParentVolume.XChunkSize == 0 && (x - 1) >= 0) { AddChunkToUpdateList((x - 1) / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize); } if (x % ParentVolume.XChunkSize == ParentVolume.XChunkSize - 1 && (x + 1) < XSize) { AddChunkToUpdateList((x + 1) / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize); } if (y % ParentVolume.YChunkSize == 0 && (y - 1) >= 0) { AddChunkToUpdateList(x / ParentVolume.XChunkSize, (y - 1) / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize); } if (y % ParentVolume.YChunkSize == ParentVolume.YChunkSize - 1 && (y + 1) < YSize) { AddChunkToUpdateList(x / ParentVolume.XChunkSize, (y + 1) / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize); } if (z % ParentVolume.ZChunkSize == 0 && (z - 1) >= 0) { AddChunkToUpdateList(x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, (z - 1) / ParentVolume.ZChunkSize); } if (z % ParentVolume.ZChunkSize == ParentVolume.ZChunkSize - 1 && (z + 1) < ZSize) { AddChunkToUpdateList(x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, (z + 1) / ParentVolume.ZChunkSize); } }
/// <summary> /// Attempts to set a voxel's state within this frame, at a given world position, to the supplied value /// </summary> /// <param name="pos">The world position in the scene</param> /// <param name="state">The new voxel state to set to</param> public Vector3 SetVoxelStateAtWorldPosition(Vector3 pos, VoxelState state) { Vector3 localPos = transform.InverseTransformPoint(pos); Vector3 arrayPos = new Vector3((int)(localPos.x / ParentVolume.VoxelSize), (int)(localPos.y / ParentVolume.VoxelSize), (int)(localPos.z / ParentVolume.VoxelSize)); SetVoxelStateAtArrayPosition((int)arrayPos.x, (int)arrayPos.y, (int)arrayPos.z, state); return(arrayPos); }
private void GetPlayerInputs() { if (Input.GetKeyDown(KeyCode.Escape)) { Application.Quit(); } horizontal = Input.GetAxis("Horizontal"); vertical = Input.GetAxis("Vertical"); mouseHorizontal = Input.GetAxis("Mouse X"); mouseVertical = Input.GetAxis("Mouse Y"); if (Input.GetButtonDown("Sprint")) { isSprinting = true; } if (Input.GetButtonUp("Sprint")) { isSprinting = false; } if (isGrounded && Input.GetButtonDown("Jump")) { jumpRequest = true; } if (highlightBlock.gameObject.activeSelf) { // Destroy block. if (Input.GetMouseButtonDown(0)) { VoxelState temp = world.GetVoxelState(highlightBlock.position); Debug.Log(temp.id); byte gotIdx = toolbar.getSlotItemIndex(temp.id); if (toolbar.slots[gotIdx].HasItem) { toolbar.slots[gotIdx].itemSlot.stack.amount++; } world.GetChunkFromVector3(highlightBlock.position).EditVoxel(highlightBlock.position, 0); } // Place block. if (Input.GetMouseButtonDown(1)) { if (toolbar.slots[toolbar.slotIndex].HasItem) { world.GetChunkFromVector3(placeBlock.position).EditVoxel(placeBlock.position, toolbar.slots[toolbar.slotIndex].itemSlot.stack.id); toolbar.slots[toolbar.slotIndex].itemSlot.Take(1); } } } }
/// <summary> /// Deserialise this voxel from a byte array /// </summary> /// <param name="bytes">A byte array representing a single voxel</param> public Voxel(byte[] bytes) { if (bytes.Length != BYTE_SIZE) { State = VoxelState.Inactive; Value = 128; Color = UnityEngine.Color.black; } State = (VoxelState)bytes[0]; Value = bytes[1]; Color = new Color32(bytes[2], bytes[3], bytes[4], bytes[5]); }
/// <summary> /// Attempts to set a voxel's state within this volume's current frame, at a given world position, to the supplied value /// </summary> /// <param name="pos">The world position in the scene</param> /// <param name="state">The new voxel state to set to</param> /// <returns>The array position of the voxel</returns> public Vector3 SetVoxelStateAtWorldPosition(Vector3 pos, VoxelState state) { return Frames[CurrentFrame].SetVoxelStateAtWorldPosition(pos, state); }
/// <summary> /// Attempts to set a voxel's state within this volume's current frame, at a specified array position /// </summary> /// <param name="pos">A PicaVoxelPoint location within the 3D array of voxels</param> /// <param name="state">The new state to set to</param> public void SetVoxelStateAtArrayPosition(PicaVoxelPoint pos, VoxelState state) { Frames[CurrentFrame].SetVoxelStateAtArrayPosition(pos, state); }
/// <summary> /// Attempts to set a voxel's state within this volume's current frame, at a specified x,y,z array position /// </summary> /// <param name="x">X array position</param> /// <param name="y">Y array position</param> /// <param name="z">Z array position</param> /// <param name="state">The new state to set to</param> public void SetVoxelStateAtArrayPosition(int x, int y, int z, VoxelState state) { Frames[CurrentFrame].SetVoxelStateAtArrayPosition(x, y, z, state); }
/// <summary> /// Attempts to set a voxel's state within this frame, at a specified x,y,z array position /// </summary> /// <param name="x">X array position</param> /// <param name="y">Y array position</param> /// <param name="z">Z array position</param> /// <param name="state">The new voxel state to set to</param> public void SetVoxelStateAtArrayPosition(int x, int y, int z, VoxelState state) { if (x < 0 || y < 0 || z < 0 || x >= XSize || y >= YSize || z >= ZSize) return; bool updateVox = false; int index = x + XSize * (y + YSize * z); if (state != Voxels[index].State) updateVox = true; Voxels[index].State = state; if (!updateVox) return; if (chunks == null) GetChunkReferences(); chunks[x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize].IsUpdated = true; // If we're at the edge of a chunk, we should update the next voxel as well if (x % ParentVolume.XChunkSize == 0 && (x - 1) >= 0) chunks[(x - 1) / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize].IsUpdated = true; if (x % ParentVolume.XChunkSize == ParentVolume.XChunkSize - 1 && (x + 1) < XSize) chunks[(x + 1) / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize].IsUpdated = true; if (y % ParentVolume.YChunkSize == 0 && (y - 1) >= 0) chunks[x / ParentVolume.XChunkSize, (y - 1) / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize].IsUpdated = true; if (y % ParentVolume.YChunkSize == ParentVolume.YChunkSize - 1 && (y + 1) < YSize) chunks[x / ParentVolume.XChunkSize, (y + 1) / ParentVolume.YChunkSize, z / ParentVolume.ZChunkSize].IsUpdated = true; if (z % ParentVolume.ZChunkSize == 0 && (z - 1) >= 0) chunks[x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, (z - 1) / ParentVolume.ZChunkSize].IsUpdated = true; if (z % ParentVolume.ZChunkSize == ParentVolume.ZChunkSize - 1 && (z + 1) < ZSize) chunks[x / ParentVolume.XChunkSize, y / ParentVolume.YChunkSize, (z + 1) / ParentVolume.ZChunkSize].IsUpdated = true; }
/// <summary> /// Attempts to set a voxel's state within this frame, at a specified array position /// </summary> /// <param name="pos">A PicaVoxelPoint location within the 3D array of voxels</param> /// <param name="state">The new state to set to</param> public void SetVoxelStateAtArrayPosition(PicaVoxelPoint pos, VoxelState state) { SetVoxelStateAtArrayPosition(pos.X, pos.Y, pos.Z, state); }
/// <summary> /// Attempts to set a voxel's state within this frame, at a given world position, to the supplied value /// </summary> /// <param name="pos">The world position in the scene</param> /// <param name="state">The new voxel state to set to</param> public Vector3 SetVoxelStateAtWorldPosition(Vector3 pos, VoxelState state) { Vector3 localPos = transform.InverseTransformPoint(pos); Vector3 arrayPos = new Vector3((int)(localPos.x / ParentVolume.VoxelSize), (int)(localPos.y / ParentVolume.VoxelSize), (int)(localPos.z / ParentVolume.VoxelSize)); SetVoxelStateAtArrayPosition((int)arrayPos.x, (int)arrayPos.y, (int)arrayPos.z, state); return arrayPos; }