private void SpreadVerticalInPos(int x, int y, int z, Chunk chunk, int curLightLevel) { //光照强度小于等于1时不再传播 if (curLightLevel < 2) { return; } //当前高度大于光照高度,不再传播 if (y >= chunk.GetHeight(x, z, true)) { SetLight(chunk, x, y, z, WorldConfig.Instance.maxLightLevel); return; } Block b = chunk.GetBlock(x, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); if (lightDamp < WorldConfig.Instance.maxLightLevel) { int lightLevel = chunk.GetSunLight(x, y, z); int nextLightLevel = curLightLevel - lightDamp - 1; if (nextLightLevel > lightLevel) { SetLight(chunk, x, y, z, nextLightLevel); } } }
public void ChangeHandObj(int id, bool isFirst) { if (id <= 0) { HideCurObj(); return; } Item item = ItemManager.Instance.GetItem(id); if (item.itemType == (int)ItemType.Block) { if (BlockAttributeCalculatorFactory.GetCalculator((BlockType)item.sceneBlockType).GetBlockRenderType(item.sceneBlockExtendId) == BlockRenderType.Part) { ChangeSurfaceObj((BlockType)item.sceneBlockType, item.sceneBlockExtendId, isFirst); } else { ChangeCubeObj((BlockType)item.sceneBlockType, item.sceneBlockExtendId, isFirst); } } else { ChangeModelObj(id, isFirst); } }
public void SetBlock(int x, int y, int z, Block block, bool isInRange = false) { if (!isInRange && !IsInRange(x, y, z)) { chunk.SetBlock(x, chunkOffsetY + y, z, block); } else { Block b = GetRealBlock(x, y, z); BlockAttributeCalculator old = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); BlockRenderType oldRenderType = old.GetBlockRenderType(b.ExtendId); if (oldRenderType != BlockRenderType.None) { visibleBlocks--; } if (oldRenderType == BlockRenderType.Part) { specialBlocks--; } BlockAttributeCalculator cur = BlockAttributeCalculatorFactory.GetCalculator(block.BlockType); BlockRenderType curRenderType = cur.GetBlockRenderType(block.ExtendId); if (curRenderType != BlockRenderType.None) { visibleBlocks++; } if (curRenderType == BlockRenderType.Part) { specialBlocks++; } SetRealBlock(x, y, z, block); chunk.isUpdate = true; } }
private void ShrinkHorizontalInPos(int x, int y, int z, Chunk chunk, int prevLightLevel, int curLightLevel) { //当前光照强度为最大值时不收缩 if (curLightLevel >= WorldConfig.Instance.maxLightLevel) { return; } //当前高度大于光照高度,不再收缩,直接从旁边扩散 if (y >= chunk.GetHeight(x, z, true)) { int lightLevel = chunk.GetSunLight(x, y, z); int nextIndex = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, lightLevel, chunk)); return; } Block b = chunk.GetBlock(x, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); if (lightDamp < WorldConfig.Instance.maxLightLevel) { int lightLevel = chunk.GetSunLight(x, y, z); if (lightLevel > 0) { int temp = prevLightLevel - lightDamp; //如果前一个物块比当前物块的太阳光亮,那么减弱当前物块的亮度 if (temp > lightLevel) { int nextLightLevel = curLightLevel - lightDamp - 1; if (nextLightLevel < 0) { nextLightLevel = 0; } //如果最终结果没有发生改变,那么不收缩 if (nextLightLevel == lightLevel) { return; } chunk.SetSunLight(x, y, z, nextLightLevel, true); if (!_changedList.Contains(chunk)) { _changedList.Add(chunk); } int nextIndex = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightBfsQueue.Enqueue(NodeCache.Instance.GetShrinkNode(nextIndex, lightLevel, nextLightLevel, chunk)); } //如果前一个物块比当前物块的太阳光暗,那么增强前一个物块的亮度 else if (temp < lightLevel) { int nextIndex = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, lightLevel, chunk)); } } } }
private void SpreadInPosDown(int x, int y, int z, Chunk chunk, int prevLightLevel, int curLightLevel) { if (curLightLevel >= WorldConfig.Instance.maxLightLevel) { return; } //当前高度大于光照高度,往下收缩,不管亮度是否大于自己 if (y >= chunk.GetHeight(x, z, true)) { return; } Block b = chunk.GetBlock(x, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); if (lightDamp < WorldConfig.Instance.maxLightLevel) { int lightLevel = chunk.GetSunLight(x, y, z); if (lightLevel > 0) { int temp = prevLightLevel - lightDamp; //向下收缩,考虑到都为15的情况,相等的情况下也收缩掉 if (temp > lightLevel || (temp <= WorldConfig.Instance.maxLightLevel && lightLevel == WorldConfig.Instance.maxLightLevel)) { int nextLightLevel = curLightLevel - lightDamp - 1; if (nextLightLevel < 0) { nextLightLevel = 0; } if (nextLightLevel == lightLevel) { return; } chunk.SetSunLight(x, y, z, nextLightLevel, true); if (!_changedList.Contains(chunk)) { _changedList.Add(chunk); } int nextIndex = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; if (temp <= WorldConfig.Instance.maxLightLevel && lightLevel == WorldConfig.Instance.maxLightLevel) { lightLevel = nextLightLevel; } _lightBfsQueue.Enqueue(NodeCache.Instance.GetShrinkNode(nextIndex, lightLevel, nextLightLevel, chunk)); } //如果前一个物块比当前物块的太阳光暗,那么增强前一个物块的亮度 else if (temp < lightLevel) { int nextIndex = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, lightLevel, chunk)); } } } }
protected void AddUV(FilterMeshData filterMeshData, BlockType type, byte extendId, Direction direction) { BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(type); Rect uvRect = calculator.GetUVRect(extendId, direction); float scale = uvRect.width * 0.03f; filterMeshData.uv.Add(new Vector2(uvRect.x + uvRect.width - scale, uvRect.y + uvRect.height - scale)); filterMeshData.uv.Add(new Vector2(uvRect.x + scale, uvRect.y + uvRect.height - scale)); filterMeshData.uv.Add(new Vector2(uvRect.x + scale, uvRect.y + scale)); filterMeshData.uv.Add(new Vector2(uvRect.x + uvRect.width - scale, uvRect.y + scale)); }
private void UpdateSunLightHeight(int x, int y, int z, Block block) { int height = GetHeight(x, z); height = y <= height ? height : y + 1; bool isLight = true; int sunLightLevel = WorldConfig.Instance.maxLightLevel; int ty; for (ty = height - 1; ty >= 0; ty--) { Block b = GetBlock(x, ty, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); if (lightDamp != 0 && isLight) { SetHeight(x, z, ty + 1); isLight = false; } sunLightLevel -= lightDamp; if (sunLightLevel < 0) { sunLightLevel = 0; } SetSunLight(x, ty, z, sunLightLevel); if (sunLightLevel == 0) { break; } } height = ty - 1; for (ty = height; ty >= 0; ty--) { if (GetSunLight(x, ty, z) > 0) { SetSunLight(x, ty, z, 0); } else { break; } } }
private void CreateExplodeParticle(WorldPos pos, Block block, Vector3 normal) { ParticleSystem explode = particleQueue.Dequeue(); Renderer render = explode.GetComponent <Renderer>(); Direction dir = Direction.left; //更新光照 int direction = CheckNormal(normal); WorldPos lightPos = pos; if (direction != 0) { dir = (Direction)direction; lightPos = new WorldPos(pos.x + Mathf.RoundToInt(normal.x), pos.y + Mathf.RoundToInt(normal.y), pos.z + Mathf.RoundToInt(normal.z)); } int sunLightLevel = World.world.GetSunLight(lightPos.x, lightPos.y, lightPos.z); int blockLightLevel = World.world.GetBlockLight(lightPos.x, lightPos.y, lightPos.z); float lightIntensity = MTBSkyBox.Instance.GetLightIntensity(sunLightLevel, blockLightLevel); render.material.SetFloat("_lightIntensity", lightIntensity); //更新贴图 ResetExplode(explode); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(block.BlockType); byte resExtendId = calculator.GetResourceExtendId(block.ExtendId); WorldTextureType type = WorldTextureProvider.Instance.GetTextureType(block.BlockType, resExtendId); render.material.mainTexture = WorldTextureProvider.Instance.GetAtlasTexture(type); Rect rect = WorldTextureProvider.Instance.GetBlockTextureRect(block.BlockType, resExtendId, dir); if (rect != null) { render.material.SetFloat("_OffsetX", rect.x); render.material.SetFloat("_OffsetY", rect.y); render.material.SetFloat("_Width", rect.width); render.material.SetFloat("_Random", UnityEngine.Random.Range(0, 1f)); explode.transform.position = new Vector3(pos.x + 0.5f, pos.y + 0.1f, pos.z + 0.5f); } explode.Play(); particleQueue.Enqueue(explode); }
void Update() { if (!_isFly) { _curTime += Time.deltaTime; if (_curTime > disappearTime) { On_SelfDisappear(this); } WorldPos pos = Terrain.GetWorldPos(this.transform.position); Block block = World.world.GetBlock(pos.x, pos.y, pos.z); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(block.BlockType); int sunLight = World.world.GetSunLight(pos.x, pos.y, pos.z); int blockLight = World.world.GetBlockLight(pos.x, pos.y, pos.z); float lightIntensity = MTBSkyBox.Instance.GetLightIntensity(sunLight, blockLight); render.material.SetFloat("_lightIntensity", lightIntensity); if (calculator.GetMeshColliderType(block.ExtendId) == MeshColliderType.terrainCollider) { On_SelfDisappear(this); } } else { if (_player != null) { Vector3 dis = _player.transform.position + new Vector3(0, 1.5f, 0) - this.transform.position; if (dis.magnitude < 0.3f) { On_SelfDisappear(this); return; } Vector3 v = dis.normalized * flySpeed; this.transform.position += v * Time.deltaTime; } else { On_SelfDisappear(this); } } }
public void SetBlockAndNotify(World world, int x, int y, int z, Block block, bool notify = true) { Block oldBlock = world.GetBlock(x, y, z); world.SetBlock(x, y, z, block); //当有玩家对物块进行操作时,同步物块数据 Chunk chunk = world.GetChunk(x, y, z); if (chunk != null && chunk.isPopulationDataPrepared) { int tempX = x - chunk.worldPos.x; int tempY = y - chunk.worldPos.y; int tempZ = z - chunk.worldPos.z; EventManager.SendEvent(EventMacro.BLOCK_DATA_UPDATE_AFTER_POPULATION, chunk.worldPos, tempX, tempY, tempZ, block); } if (notify) { IBlockNotify oldNotify = BlockAttributeCalculatorFactory.GetCalculator(oldBlock.BlockType); oldNotify.NotifySelf(world, x, y, z, oldBlock, block); NotifyAround(world, x, y, z, oldBlock, block); } }
private List <Chunk> GetBlockLightChangeChunks(Chunk chunk, int x, int y, int z, Block b, List <Chunk> list) { BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int curBlockLightLevel = calculator.LightLevel(b.ExtendId); int blockLightLevel = chunk.GetBlockLight(x, y, z, true); if (curBlockLightLevel > blockLightLevel) { int index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; LightSpreadNode node = NodeCache.Instance.GetSpreadNode(index, curBlockLightLevel, chunk); _blockLightSpread.AddSpreadNode(node); chunk.SetBlockLight(x, y, z, curBlockLightLevel, true); } else if (curBlockLightLevel < blockLightLevel) { int index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; LightShrinkNode node = NodeCache.Instance.GetShrinkNode(index, blockLightLevel, curBlockLightLevel, chunk); _blockLightShrink.AddShrinkNode(node); chunk.SetBlockLight(x, y, z, curBlockLightLevel, true); } List <Chunk> spreadList = _blockLightSpread.SpreadInChunk(chunk); List <Chunk> shrinkList = _blockLightShrink.ShrinkInChunk(chunk); for (int i = 0; i < spreadList.Count; i++) { if (!list.Contains(spreadList[i])) { list.Add(spreadList[i]); } } for (int i = 0; i < shrinkList.Count; i++) { if (!list.Contains(shrinkList[i])) { list.Add(shrinkList[i]); } } return(list); }
public override void SetBlock(World world, int x, int y, int z, Block block, bool notify = true) { if (!IsHeightLimit(y)) { return; } BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(block.BlockType); Direction direction = calculator.GetFaceDirection(block.ExtendId); WorldPos offset = new WorldPos(); if (direction == Direction.front) { offset = new WorldPos(x - 1, y, z); } if (direction == Direction.back) { offset = new WorldPos(x + 1, y, z); } if (direction == Direction.left) { offset = new WorldPos(x, y, z - 1); } if (direction == Direction.right) { offset = new WorldPos(x, y, z + 1); } byte extendId = (byte)(block.ExtendId & 7); if (world.GetBlock(offset.x, offset.y, offset.z).BlockType != BlockType.Air) { return; } Block tempBlock = new Block(block.BlockType, extendId); SetBlockAndNotify(world, offset.x, offset.y, offset.z, tempBlock); SetBlockAndNotify(world, x, y, z, block); world.CheckAndRecalculateMesh(offset.x, offset.y, offset.z, tempBlock); world.CheckAndRecalculateMesh(x, y, z, block); }
private void NormalSunLightFill(Chunk chunk) { int sunLightLevel; bool isLight; for (int x = 0; x < Chunk.chunkWidth; x++) { for (int z = 0; z < Chunk.chunkDepth; z++) { sunLightLevel = WorldConfig.Instance.maxLightLevel; isLight = true; for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block b = chunk.GetBlock(x, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); if (lightDamp != 0 && isLight) { chunk.SetHeight(x, z, y + 1); isLight = false; } sunLightLevel -= lightDamp; if (sunLightLevel > 0) { chunk.SetSunLight(x, y, z, sunLightLevel); } else { break; } } } } }
private void SpreadFromOtherChunk(Chunk chunk) { Chunk otherChunk; //curChunk_X - 1 otherChunk = _world.GetChunk(chunk.worldPos.x - Chunk.chunkWidth, 0, chunk.worldPos.z); if (otherChunk != null && otherChunk.isLightDataPrepared) { for (int z = 0; z < Chunk.chunkDepth; z++) { for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block curBlock = chunk.GetBlock(0, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(curBlock.BlockType); int lightDamp = calculator.LightDamp(curBlock.ExtendId); if (lightDamp < 15) { int curLightLevel = chunk.GetSunLight(0, y, z, true); int otherLightLevel = otherChunk.GetSunLight(Chunk.chunkWidth - 1, y, z, true); int nextLightLevel = otherLightLevel - lightDamp - 1; if (nextLightLevel > curLightLevel) { chunk.SetSunLight(0, y, z, nextLightLevel, true); int nextIndex = (0 * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, nextLightLevel, chunk)); } } } } } //curChunk_x + Chunk.chunkWidth otherChunk = _world.GetChunk(chunk.worldPos.x + Chunk.chunkWidth, 0, chunk.worldPos.z); if (otherChunk != null && otherChunk.isLightDataPrepared) { for (int z = 0; z < Chunk.chunkDepth; z++) { for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block curBlock = chunk.GetBlock(Chunk.chunkWidth - 1, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(curBlock.BlockType); int lightDamp = calculator.LightDamp(curBlock.ExtendId); if (lightDamp < 15) { int curLightLevel = chunk.GetSunLight(Chunk.chunkWidth - 1, y, z, true); int otherLightLevel = otherChunk.GetSunLight(0, y, z, true); int nextLightLevel = otherLightLevel - lightDamp - 1; if (nextLightLevel > curLightLevel) { chunk.SetSunLight(Chunk.chunkWidth - 1, y, z, nextLightLevel, true); int nextIndex = ((Chunk.chunkWidth - 1) * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, nextLightLevel, chunk)); } } } } } //curChunk_z - Chunk.chunkDepth otherChunk = _world.GetChunk(chunk.worldPos.x, 0, chunk.worldPos.z - Chunk.chunkDepth); if (otherChunk != null && otherChunk.isLightDataPrepared) { for (int x = 0; x < Chunk.chunkDepth; x++) { for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block curBlock = chunk.GetBlock(x, y, 0, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(curBlock.BlockType); int lightDamp = calculator.LightDamp(curBlock.ExtendId); if (lightDamp < 15) { int curLightLevel = chunk.GetSunLight(x, y, 0, true); int otherLightLevel = otherChunk.GetSunLight(x, y, Chunk.chunkDepth - 1, true); int nextLightLevel = otherLightLevel - lightDamp - 1; if (nextLightLevel > curLightLevel) { chunk.SetSunLight(x, y, 0, nextLightLevel, true); int nextIndex = (x * Chunk.chunkDepth + 0) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, nextLightLevel, chunk)); } } } } } //curChunk_z + Chunk.chunkDepth otherChunk = _world.GetChunk(chunk.worldPos.x, 0, chunk.worldPos.z + Chunk.chunkDepth); if (otherChunk != null && otherChunk.isLightDataPrepared) { for (int x = 0; x < Chunk.chunkDepth; x++) { for (int y = Chunk.chunkHeight - 1; y >= 0; y--) { Block curBlock = chunk.GetBlock(x, y, Chunk.chunkDepth - 1, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(curBlock.BlockType); int lightDamp = calculator.LightDamp(curBlock.ExtendId); if (lightDamp < 15) { int curLightLevel = chunk.GetSunLight(x, y, Chunk.chunkDepth - 1, true); int otherLightLevel = otherChunk.GetSunLight(x, y, 0, true); int nextLightLevel = otherLightLevel - lightDamp - 1; if (nextLightLevel > curLightLevel) { chunk.SetSunLight(x, y, Chunk.chunkDepth - 1, nextLightLevel, true); int nextIndex = (x * Chunk.chunkDepth + Chunk.chunkDepth - 1) * Chunk.chunkHeight + y; _lightSpread.AddSpreadNode(NodeCache.Instance.GetSpreadNode(nextIndex, nextLightLevel, chunk)); } } } } } }
public void CalculateSectionMesh(Section section, MeshData meshData) { MeshCalculateWay way = GetCalculateWay(section); if (way == MeshCalculateWay.None) { return; } for (int d = 0; d < 3; d++) { int i, j, k, l, w, h, u = (d + 1) % 3, v = (d + 2) % 3; ClearIntArr(x); ClearIntArr(q); // int[] x = new int[]{0,0,0}; // int[] q = new int[]{0,0,0}; int direction = d + 1; q[d] = 1; if (way == MeshCalculateWay.Side) { x[d] = dims[d] - 1; } else { x[d] = 0; } for (; x[d] < dims[d];) { int n = 0; bool bBInRange = x[d] < dims[d] - 1; for (x[v] = 0; x[v] < dims[v]; x[v]++) { for (x[u] = 0; x[u] < dims[u]; x[u]++) { int x1 = x[0], y1 = x[1], z1 = x[2], x2 = x1 + q[0], y2 = y1 + q[1], z2 = z1 + q[2]; Block bA = (x[d] < 1 || way == MeshCalculateWay.Side) ? section.GetBlock(x1, y1, z1, true) : _prevBlocks[n]; BlockAttributeCalculator aBAC = BlockAttributeCalculatorFactory.GetCalculator(bA.BlockType); Block bB = section.GetBlock(x2, y2, z2, bBInRange); BlockAttributeCalculator bBAC = BlockAttributeCalculatorFactory.GetCalculator(bB.BlockType); CalculateRenderMesh(section.chunk, meshData, x1, y1 + section.chunkOffsetY, z1, x2, y2 + section.chunkOffsetY, z2, bA, bB, aBAC, bBAC, direction, bBInRange); RefreshRenderMask(_renderMask, _renderDirectionMask, _curRenderBlocks, _sunLightsMask, _blockLightsMask, n, section, x1, y1, z1, x2, y2, z2, bA, bB, aBAC, bBAC, bBInRange, direction); RefreshColliderMask(_faceMask, _colliderMask, n, bA, bB, aBAC, bBAC, direction); _prevBlocks[n] = bB; n++; } } x[d]++; // //贪心简化碰撞网格 // n = 0; // for (j = 0; j < dims[v]; j++) { // for (i = 0; i < dims[u];) { // bool c = _faceMask[n]; // MeshColliderType c1 = _colliderMask[n]; // if(c1 != MeshColliderType.none) // { // for (w = 1;i + w < dims[u] && c1 == _colliderMask[n + w] && c == _faceMask[n + w] ; w++); // bool done = false; // for (h = 1; j + h < dims[v]; h++) { // for (k = 0; k < w; k++) { // int doneIndex = n + k + h * dims[u]; // if(c1 != _colliderMask[doneIndex] || c != _faceMask[doneIndex]) // { // done = true; // break; // } // } // if(done)break; // } // // x[u] = i; x[v] = j; // ClearIntArr(du); // ClearIntArr(dv); //// int[] du = new int[]{0,0,0}; //// int[] dv = new int[]{0,0,0}; // du[u] = w; // dv[v] = h; // //因为shader的需求,这边不能-0.5 // AddFace(c,c1,meshData,MeshBaseDataCache.Instance.GetVector3(x[0],x[1] + section.chunkOffsetY,x[2]), // MeshBaseDataCache.Instance.GetVector3(x[0] + du[0],x[1] + du[1] + section.chunkOffsetY,x[2] + du[2]), // MeshBaseDataCache.Instance.GetVector3(x[0] + du[0] + dv[0],x[1] + du[1] + dv[1] + section.chunkOffsetY,x[2] + du[2] + dv[2]), // MeshBaseDataCache.Instance.GetVector3(x[0] + dv[0],x[1] + dv[1] + section.chunkOffsetY,x[2] + dv[2])); // for (l = 0; l < h; l++) { // for (k = 0; k < w; k++) { // int maskIndex = n + k + l * dims[u]; // _faceMask[maskIndex] = true; // _colliderMask[maskIndex] = MeshColliderType.none; // } // } // i+=w; // n+=w; // } // else // { // i++;n++; // } // } // } //贪心简化渲染网格 n = 0; for (j = 0; j < dims[v]; j++) { for (i = 0; i < dims[u];) { bool canRender = _renderMask[n]; Direction renderDirection = _renderDirectionMask[n]; Block curBlock = _curRenderBlocks[n]; BlockAttributeCalculator curCalculator = BlockAttributeCalculatorFactory.GetCalculator(curBlock.BlockType); LightVertice sunLight = _sunLightsMask[n]; LightVertice blockLight = _blockLightsMask[n]; if (canRender) { for (w = 1; i + w < dims[u] && _renderMask[n + w] && renderDirection == _renderDirectionMask[n + w] && curCalculator.CanCombineWithBlock(curBlock.ExtendId, _curRenderBlocks[n + w]) && sunLight.EqualOther(_sunLightsMask[n + w]) && blockLight.EqualOther(_blockLightsMask[n + w]); w++) { ; } bool done = false; for (h = 1; j + h < dims[v]; h++) { for (k = 0; k < w; k++) { int doneIndex = n + k + h * dims[u]; if (!_renderMask[doneIndex] || renderDirection != _renderDirectionMask[doneIndex] || !curCalculator.CanCombineWithBlock(curBlock.ExtendId, _curRenderBlocks[doneIndex]) || !sunLight.EqualOther(_sunLightsMask[doneIndex]) || !blockLight.EqualOther(_blockLightsMask[doneIndex])) { done = true; break; } } if (done) { break; } } x[u] = i; x[v] = j; ClearIntArr(du); ClearIntArr(dv); // int[] du = new int[]{0,0,0}; // int[] dv = new int[]{0,0,0}; du[u] = w; dv[v] = h; curCalculator.CalculateMesh(section.chunk, meshData, curBlock, renderDirection, MeshBaseDataCache.Instance.GetVector3(x[0], x[1] + section.chunkOffsetY, x[2]), MeshBaseDataCache.Instance.GetVector3(x[0] + du[0], x[1] + du[1] + section.chunkOffsetY, x[2] + du[2]), MeshBaseDataCache.Instance.GetVector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1] + section.chunkOffsetY, x[2] + du[2] + dv[2]), MeshBaseDataCache.Instance.GetVector3(x[0] + dv[0], x[1] + dv[1] + section.chunkOffsetY, x[2] + dv[2]), sunLight, blockLight); for (l = 0; l < h; l++) { for (k = 0; k < w; k++) { int maskIndex = n + k + l * dims[u]; _renderMask[maskIndex] = false; } } i += w; n += w; } else { i++; n++; } } } } } //计算boxcollider int nn = 0; for (int y = 0; y < dims[1]; y++) { for (int x = 0; x < dims[0]; x++) { for (int z = 0; z < dims[2]; z++) { Block block = section.GetBlock(x, y, z, true); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(block.BlockType); MeshColliderType colliderType = calculator.GetMeshColliderType(block.ExtendId); _terrainColliderMask[nn] = colliderType; nn++; } } } nn = 0; int dd; int ww; int hh; int kk; int ll; int mm; for (int y = 0; y < dims[1]; y++) { for (int x = 0; x < dims[0]; x++) { for (int z = 0; z < dims[2];) { MeshColliderType flag = _terrainColliderMask[nn]; if (flag != MeshColliderType.none) { for (dd = 1; z + dd < dims[2] && flag == _terrainColliderMask[nn + dd]; dd++) { ; } bool done = false; for (ww = 1; x + ww < dims[0]; ww++) { for (kk = 0; kk < dd; kk++) { int doneIndex = nn + kk + ww * dims[2]; if (flag != _terrainColliderMask[doneIndex]) { done = true; break; } } if (done) { break; } } done = false; for (hh = 1; y + hh < dims[1]; hh++) { for (ll = 0; ll < ww; ll++) { for (kk = 0; kk < dd; kk++) { int doneIndex = nn + kk + ll * dims[2] + hh * dims[0] * dims[2]; if (flag != _terrainColliderMask[doneIndex]) { done = true; break; } } if (done) { break; } } if (done) { break; } } Vector3 min = new Vector3(x, y, z); Vector3 max = new Vector3(x + ww, y + hh, z + dd); Vector3 center = (min + max) / 2; center.y += section.chunkOffsetY; Vector3 size = max - min; if (flag == MeshColliderType.terrainCollider) { meshData.terrainCollider.AddBox(center, size); } else { meshData.supportCollider.AddBox(center, size); } for (mm = 0; mm < hh; mm++) { for (ll = 0; ll < ww; ll++) { for (kk = 0; kk < dd; kk++) { int maskIndex = nn + kk + ll * dims[2] + mm * dims[0] * dims[2]; _terrainColliderMask[maskIndex] = MeshColliderType.none; } } } nn += dd; z += dd; } else { nn++; z++; } } } } }
private List <Chunk> GetSunLightChangeChunks(Chunk chunk, int x, int y, int z, Block b, List <Chunk> list) { List <Chunk> spreadList = null; List <Chunk> shrinkList = null; BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(b.BlockType); int lightDamp = calculator.LightDamp(b.ExtendId); int height = chunk.GetHeight(x, z); int lightLevel = chunk.GetSunLight(x, y, z, true); int curLightLevel; if (y >= height - 1) { for (int ty = y; ty >= height; ty--) { Block nextBlock = chunk.GetBlock(x, ty, z); BlockAttributeCalculator nextCalculator = BlockAttributeCalculatorFactory.GetCalculator(nextBlock.BlockType); int nextLightDamp = nextCalculator.LightDamp(nextBlock.ExtendId); if (nextLightDamp > 0) { height = ty + 1; //更新高度 chunk.SetHeight(x, z, height, true); break; } } curLightLevel = WorldConfig.Instance.maxLightLevel - lightDamp; if (curLightLevel < 0) { curLightLevel = 0; } } else { int leftSunLight = chunk.GetSunLight(x - 1, y, z); int rightSunLight = chunk.GetSunLight(x + 1, y, z); int topSunLight = chunk.GetSunLight(x, y + 1, z); int bottomSunLight = chunk.GetSunLight(x, y - 1, z); int frontSunLight = chunk.GetSunLight(x, y, z + 1); int backSunLight = chunk.GetSunLight(x, y, z - 1); int maxSunLight = GetMax(leftSunLight, rightSunLight, topSunLight, bottomSunLight, frontSunLight, backSunLight); curLightLevel = maxSunLight - lightDamp - 1; if (curLightLevel < 0) { curLightLevel = 0; } } if (curLightLevel < lightLevel) { chunk.SetSunLight(x, y, z, curLightLevel, true); int index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; LightShrinkNode node = NodeCache.Instance.GetShrinkNode(index, lightLevel, curLightLevel, chunk); _sunLightShrink.AddShrinkNode(node); shrinkList = _sunLightShrink.ShrinkInChunk(chunk); } else if (curLightLevel > lightLevel) { chunk.SetSunLight(x, y, z, curLightLevel, true); int index = (x * Chunk.chunkDepth + z) * Chunk.chunkHeight + y; LightSpreadNode node = NodeCache.Instance.GetSpreadNode(index, curLightLevel, chunk); _sunLightSpread.AddSpreadNode(node); spreadList = _sunLightSpread.SpreadInChunk(chunk); } if (spreadList != null) { for (int i = 0; i < spreadList.Count; i++) { if (!list.Contains(spreadList[i])) { list.Add(spreadList[i]); } } } if (shrinkList != null) { for (int i = 0; i < shrinkList.Count; i++) { if (!list.Contains(shrinkList[i])) { list.Add(shrinkList[i]); } } } return(list); }
private IBlockNotify GetBlockNotify(World world, int x, int y, int z) { Block b = world.GetBlock(x, y, z); return(BlockAttributeCalculatorFactory.GetCalculator(b.BlockType)); }
public override void ActionIn() { float screenX = _playerController.playerInputState.X; float screenY = _playerController.playerInputState.Y; BlockMaskController.Instance.Do(screenX, screenY, _playerController.transform.position, distance); RaycastHit hit; int handMaterialId = _playerController.playerAttribute.handMaterialId; if (handMaterialId <= 0) { return; } Item item = ItemManager.Instance.GetItem(handMaterialId); if (item.itemType != (int)ItemType.Block) { return; } if (Terrain.RayToWorld(screenX, screenY, _playerController.transform.position, distance, out hit, oppoMaskLayer)) { WorldPos pos = Terrain.GetWorldPos(hit, true); if (hit.collider.GetComponentInParent <ChunkObj>() == null) { return; } if (!Terrain.CheckPosCanPlaced(_playerController.transform, pos)) { return; } Block handBlock = new Block((BlockType)item.sceneBlockType, item.sceneBlockExtendId); BlockAttributeCalculator calculator = BlockAttributeCalculatorFactory.GetCalculator(handBlock.BlockType); if (calculator is BAC_ModelBlock) { Vector3 forward = _gameObjectController.transform.forward; float degree = Vector2.Angle(Vector2.right, new Vector2(forward.x, forward.z)); byte extendId = 8; if (degree < 45) { extendId |= 3; } else if (degree > 135) { extendId |= 1; } else if (forward.z > 0) { extendId |= 2; } handBlock = new Block(BlockType.Block_100, extendId); } int decType = HasActionObjectManager.Instance.plantManager.checkIsPlantSeedling(handMaterialId); if (decType != -1) { HasActionObjectManager.Instance.plantManager.buildPlant(new Vector3(pos.x, pos.y, pos.z), (DecorationType)decType); return; } Terrain.SetBlock(pos, handBlock); } }