/// <summary> /// Applies a brush to the terrain. /// </summary> /// <param name="type">The type/shape of the brush.</param> /// <param name="size">The size (radius) of the brush.</param> /// <param name="pos">The (real world) position to apply the brush.</param> /// <param name="val">Density to apply.</param> public static void applyBrush(BrushType type, int size, Vector3 pos, float val) { List<Node> changedNodes = new List<Node>(); float nodeWidth = NodeManager.LODSize[0]; Vector3 realPos = new Vector3(); Vector3I point = new Vector3I((int)Math.Round(pos.x / nodeWidth), (int)Math.Round(pos.y / nodeWidth), (int)Math.Round(pos.z / nodeWidth)); List<Vector3> points = getPoints(type, size, pos); for (int o = 0; o < points.Count; o++) { realPos = points[o]; Node[] editNodes = NodeManager.searchNodeContainingDensity(realPos, 0); for (int i = 0; i < editNodes.Length; i++) { Node editNode = editNodes[i]; if (editNode != null && editNode.LOD == 0) { if (!changedNodes.Contains(editNode)) changedNodes.Add(editNode); if (type == BrushType.SPHERE) { float v = val; float dist = Vector3.Distance(pos, realPos); if (val > MeshFactory.isolevel) v = 10f - ((dist / (float)size) * 5f); if (val < MeshFactory.isolevel) v = 10f + ((dist / (float)size) * 5f); } editNode.setDensityFromWorldPos(realPos, val); editNode.setMaterialFromWorldPos(realPos, materialID); } } } applyPaint(type, size + 1, pos, false); for (int i = 0; i < changedNodes.Count; i++) changedNodes[i].regenerateChunk(); }
/// <summary> /// Returns the density value at the given coordinates. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <returns></returns> public float get(Vector3I pos) { if (changeData != null) if (changeData.get(pos) > -99999f) return changeData.get(pos); return get(pos.x, pos.y, pos.z); }
/// <summary> /// Subtracts another vectory's values from this /// </summary> /// <param name="other"></param> /// <returns></returns> public Vector3I Subtract(Vector3I other) { return new Vector3I(x - other.x, y - other.y, z - other.z); }
/// <summary> /// Returns a list of points inside of a given brush type and size. /// </summary> /// <param name="type"></param> /// <param name="size"></param> /// <param name="pos"></param> /// <returns></returns> private static List<Vector3> getPoints(BrushType type, int size, Vector3 pos) { float nodeWidth = NodeManager.LODSize[0]; //这里是不是少了一个nodesize呢?先加上去看看 //但是仍旧还是一样的呢 Vector3I point = new Vector3I((int)Math.Round(pos.x / nodeWidth), (int)Math.Round(pos.y / nodeWidth), (int)Math.Round(pos.z / nodeWidth)); List<Vector3> ret = new List<Vector3>(); switch (type) { case BrushType.BOX: for (int x = 0; x <= size; x++) { for (int y = 0; y <= size; y++) { for (int z = 0; z <= size; z++) { Vector3 realPos = new Vector3(); realPos.x = ((point.x + x) * nodeWidth); realPos.y = ((point.y + y) * nodeWidth); realPos.z = ((point.z + z) * nodeWidth); //这里就类似*nodesize了,所以上面应该是不用加 ret.Add(realPos); } } } break; case BrushType.SPHERE: for (int x = -size; x < size; x++) { for (int y = -size * 2; y < size; y++) { for (int z = -size; z < size; z++) { Vector3 realPos = new Vector3(); realPos.x = ((point.x + x) * nodeWidth); realPos.y = ((point.y + y) * nodeWidth); realPos.z = ((point.z + z) * nodeWidth); if (Vector3.Distance(realPos, pos) < size * nodeWidth) { ret.Add(realPos); } } } } break; } string retStr = type+","+size+","; foreach(Vector3 v in ret){ retStr+=v+","; } Debug.Log(retStr); return ret; }
/// <summary> /// Sets the view position, and checks if chunks need to be updated /// </summary> /// <param name="pos"></param> public static void setViewPosition(Vector3 pos) { for (int i = 0; i <= maxLOD; i++) { float nWidth = LODSize[i] * nodeSize; viewChunkPos[i].x = (int)(pos.x / nWidth); viewChunkPos[i].y = (int)(pos.y / nWidth); viewChunkPos[i].z = (int)(pos.z / nWidth); } float sWidth = LODSize[0] * nodeSize * 0.5f; Vector3I newPos = new Vector3I((int)(pos.x / sWidth), (int)(pos.y / sWidth), (int)(pos.z / sWidth)); if (!curTopNode.Equals(getTopNode(pos))) { float nodeWidth = LODSize[maxLOD] * nodeSize; Vector3I diff = getTopNode(pos).Subtract(curTopNode); curTopNode = getTopNode(pos); while (diff.x > 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[0, y, z].dispose(); topNodes[0, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[2, y, z]; topNodes[2, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x--; } while (diff.x < 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[2, y, z].dispose(); topNodes[2, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[0, y, z]; topNodes[0, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) - nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x++; } while (diff.y > 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 0, z].dispose(); topNodes[x, 0, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 2, z]; topNodes[x, 2, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y--; } while (diff.y < 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 2, z].dispose(); topNodes[x, 2, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 0, z]; topNodes[x, 0, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) - nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y++; } while (diff.z > 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 0].dispose(); topNodes[x, y, 0] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 2]; topNodes[x, y, 2] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z--; } while (diff.z < 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 2].dispose(); topNodes[x, y, 2] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 0]; topNodes[x, y, 0] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) - nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z++; } } if (curBottomNode.x != newPos.x || curBottomNode.y != newPos.y || curBottomNode.z != newPos.z) { Vector3 setPos = new Vector3(newPos.x * sWidth + (sWidth / 1f), newPos.y * sWidth + (sWidth / 1f), newPos.z * sWidth + (sWidth / 1f)); for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[x, y, z].viewPosChanged(setPos); } } } curBottomNode = newPos; } }
/// <summary> /// Calculates the normal. /// </summary> /// <param name="p"></param> private static Vector3 calculateDensityNormal(Vector3I p, DensityData densities, int lod) { Vector3 normal = new Vector3(); normal.x = (densities.get(p.x + 1, p.y, p.z) - densities.get(p.x - 1, p.y, p.z)) / (NodeManager.LODSize[lod]); normal.y = (densities.get(p.x, p.y + 1, p.z) - densities.get(p.x, p.y - 1, p.z)) / (NodeManager.LODSize[lod]); normal.z = (densities.get(p.x, p.y, p.z + 1) - densities.get(p.x, p.y, p.z - 1)) / (NodeManager.LODSize[lod]); normal.Normalize(); return normal; }
/// <summary> /// Applies 'paint' to the area around the brush. /// </summary> /// <param name="type">The type/shape of the brush.</param> /// <param name="size">The size (radius) of the brush.</param> /// <param name="pos">The (real world) position to apply the brush.</param> /// <param name="regen">Set to true to have the engine regen the chunk after painting.</param> public static void applyPaint(BrushType type, int size, Vector3 pos, bool regen) { List<Node> changedNodes = new List<Node>(); float nodeWidth = NodeManager.LODSize[0]; Vector3 realPos = new Vector3(); Vector3I point = new Vector3I((int)Math.Round(pos.x / nodeWidth), (int)Math.Round(pos.y / nodeWidth), (int)Math.Round(pos.z / nodeWidth)); List<Vector3> points = getPoints(type, size, pos); for (int o = 0; o < points.Count; o++) { realPos = points[o]; Node[] editNodes = NodeManager.searchNodeContainingDensity(realPos, 0); for (int i = 0; i < editNodes.Length; i++) { Node editNode = editNodes[i]; if (editNode != null && editNode.LOD == 0) { if (!changedNodes.Contains(editNode)) changedNodes.Add(editNode); editNode.setMaterialFromWorldPos(realPos, materialID); } } } if (regen) for (int i = 0; i < changedNodes.Count; i++) changedNodes[i].regenerateChunk(); }
/// <summary> /// Sets the view position, and checks if chunks need to be updated /// </summary> /// <param name="pos"></param> public static void setViewPosition(Vector3 pos) { for (int i = 0; i <= maxLOD; i++) { float nWidth = LODSize[i] * nodeSize; viewChunkPos[i].x = (int)(pos.x / nWidth); viewChunkPos[i].y = (int)(pos.y / nWidth); viewChunkPos[i].z = (int)(pos.z / nWidth); } float sWidth = LODSize[0] * nodeSize * 0.5f; Vector3I newPos = new Vector3I((int)(pos.x / sWidth), (int)(pos.y / sWidth), (int)(pos.z / sWidth)); if (!curTopNode.Equals(getTopNode(pos))) { float nodeWidth = LODSize[maxLOD] * nodeSize; Vector3I diff = getTopNode(pos).Subtract(curTopNode); curTopNode = getTopNode(pos); while (diff.x > 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[0, y, z].dispose(); topNodes[0, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[2, y, z]; topNodes[2, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x--; } while (diff.x < 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[2, y, z].dispose(); topNodes[2, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[0, y, z]; topNodes[0, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) - nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x++; } while (diff.y > 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 0, z].dispose(); topNodes[x, 0, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 2, z]; topNodes[x, 2, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y--; } while (diff.y < 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 2, z].dispose(); topNodes[x, 2, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 0, z]; topNodes[x, 0, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) - nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y++; } while (diff.z > 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 0].dispose(); topNodes[x, y, 0] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 2]; topNodes[x, y, 2] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z--; } while (diff.z < 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 2].dispose(); topNodes[x, y, 2] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 0]; topNodes[x, y, 0] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) - nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z++; } } if (curBottomNode.x != newPos.x || curBottomNode.y != newPos.y || curBottomNode.z != newPos.z) { Vector3 setPos = new Vector3(newPos.x * sWidth + (sWidth / 1f), newPos.y * sWidth + (sWidth / 1f), newPos.z * sWidth + (sWidth / 1f)); for (int x = 0; x < 3; x++) for (int y = 0; y < 3; y++) for (int z = 0; z < 3; z++) { topNodes[x, y, z].viewPosChanged(setPos); } curBottomNode = newPos; } }
/// <summary> /// Sets the density of a point, given a world pos. /// </summary> /// <param name="worldPos"></param> public void setDensityFromWorldPos(Vector3 worldPos, float val) { worldPos = worldPos - position; Vector3I arrayPos = new Vector3I((int)Math.Round(worldPos.x) / NodeManager.LODSize[LOD], (int)Math.Round(worldPos.y) / NodeManager.LODSize[LOD], (int)Math.Round(worldPos.z) / NodeManager.LODSize[LOD]); if (arrayPos.x < -1 || arrayPos.x > 17 || arrayPos.y < -1 || arrayPos.y > 17 || arrayPos.z < -1 || arrayPos.z > 17) { Debug.Log("Wrong node. " + arrayPos + ":" + worldPos + ":" + containsDensityPoint(worldPos).ToString()); return; } densityChangeData.set(arrayPos.x, arrayPos.y, arrayPos.z, val); setPermanence(true); hasDensityChangeData = true; MeshFactory.requestSave(this); }
/// <summary> /// Returns a 3d integer vector position of the "top" (highest LOD) node that contains the given position. /// </summary> /// <param name="pos"></param> /// <returns></returns> public static Vector3I getTopNode(Vector3 pos) { Vector3I ret = new Vector3I(); ret.x = (int)Mathf.Floor(pos.x / (LODSize[maxLOD] * nodeSize)); ret.y = (int)Mathf.Floor(pos.y / (LODSize[maxLOD] * nodeSize)); ret.z = (int)Mathf.Floor(pos.z / (LODSize[maxLOD] * nodeSize)); //Debug.Log("getTopNode:"+LODSize[maxLOD]+","+NodeManager.LODSize[maxLOD]); //去掉了原来的NodeManager.反正也是在一个类里面 return ret; }
/// <summary> /// Generates the triangles for a specific voxel /// </summary> /// <param name="node">The node that contains the voxel</param> /// <param name="pos">The voxel position (Not real position) [16,16,16]</param> /// <param name="triangleList">The list used to contain triangles made so far</param> /// <param name="densities">The array that contains density information</param> /// <param name="densityNormals">The array that contains density normals</param> private static void generateTriangles(Node node, Vector3I pos, List <Triangle> triangleList, List <int> submeshIDList, int[] subMeshTriCount, DensityData densities, Vector3[, ,] densityNormals) { float size = NodeManager.LODSize[node.LOD]; float[] denses = new float[8]; denses[0] = densities.get(pos.x, pos.y, pos.z + 1); denses[1] = densities.get(pos.x + 1, pos.y, pos.z + 1); denses[2] = densities.get(pos.x + 1, pos.y, pos.z); denses[3] = densities.get(pos.x, pos.y, pos.z); denses[4] = densities.get(pos.x, pos.y + 1, pos.z + 1); denses[5] = densities.get(pos.x + 1, pos.y + 1, pos.z + 1); denses[6] = densities.get(pos.x + 1, pos.y + 1, pos.z); denses[7] = densities.get(pos.x, pos.y + 1, pos.z); byte cubeIndex = 0; if (denses[0] < isolevel) { cubeIndex |= 1; } if (denses[1] < isolevel) { cubeIndex |= 2; } if (denses[2] < isolevel) { cubeIndex |= 4; } if (denses[3] < isolevel) { cubeIndex |= 8; } if (denses[4] < isolevel) { cubeIndex |= 16; } if (denses[5] < isolevel) { cubeIndex |= 32; } if (denses[6] < isolevel) { cubeIndex |= 64; } if (denses[7] < isolevel) { cubeIndex |= 128; } if (cubeIndex == 0 || cubeIndex == 255) { return; } Vector3 origin = new Vector3((size * (pos.x)) , (size * (pos.y)) , (size * (pos.z))); Vector3[] positions = new Vector3[8]; positions[0] = new Vector3(origin.x, origin.y, origin.z + size); positions[1] = new Vector3(origin.x + size, origin.y, origin.z + size); positions[2] = new Vector3(origin.x + size, origin.y, origin.z); positions[3] = new Vector3(origin.x, origin.y, origin.z); positions[4] = new Vector3(origin.x, origin.y + size, origin.z + size); positions[5] = new Vector3(origin.x + size, origin.y + size, origin.z + size); positions[6] = new Vector3(origin.x + size, origin.y + size, origin.z); positions[7] = new Vector3(origin.x, origin.y + size, origin.z); Vector3[][] vertlist = new Vector3[12][]; if (IsBitSet(edgeTable[cubeIndex], 1)) { vertlist[0] = VertexInterp(isolevel, positions[0], positions[1], denses[0], denses[1], densityNormals[pos.x, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 2)) { vertlist[1] = VertexInterp(isolevel, positions[1], positions[2], denses[1], denses[2], densityNormals[pos.x + 1, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y, pos.z]); } if (IsBitSet(edgeTable[cubeIndex], 4)) { vertlist[2] = VertexInterp(isolevel, positions[2], positions[3], denses[2], denses[3], densityNormals[pos.x + 1, pos.y, pos.z], densityNormals[pos.x, pos.y, pos.z]); } if (IsBitSet(edgeTable[cubeIndex], 8)) { vertlist[3] = VertexInterp(isolevel, positions[3], positions[0], denses[3], denses[0], densityNormals[pos.x, pos.y, pos.z], densityNormals[pos.x, pos.y, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 16)) { vertlist[4] = VertexInterp(isolevel, positions[4], positions[5], denses[4], denses[5], densityNormals[pos.x, pos.y + 1, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 32)) { vertlist[5] = VertexInterp(isolevel, positions[5], positions[6], denses[5], denses[6], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z]); } if (IsBitSet(edgeTable[cubeIndex], 64)) { vertlist[6] = VertexInterp(isolevel, positions[6], positions[7], denses[6], denses[7], densityNormals[pos.x + 1, pos.y + 1, pos.z], densityNormals[pos.x, pos.y + 1, pos.z]); } if (IsBitSet(edgeTable[cubeIndex], 128)) { vertlist[7] = VertexInterp(isolevel, positions[7], positions[4], denses[7], denses[4], densityNormals[pos.x, pos.y + 1, pos.z], densityNormals[pos.x, pos.y + 1, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 256)) { vertlist[8] = VertexInterp(isolevel, positions[0], positions[4], denses[0], denses[4], densityNormals[pos.x, pos.y, pos.z + 1], densityNormals[pos.x, pos.y + 1, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 512)) { vertlist[9] = VertexInterp(isolevel, positions[1], positions[5], denses[1], denses[5], densityNormals[pos.x + 1, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1]); } if (IsBitSet(edgeTable[cubeIndex], 1024)) { vertlist[10] = VertexInterp(isolevel, positions[2], positions[6], denses[2], denses[6], densityNormals[pos.x + 1, pos.y, pos.z], densityNormals[pos.x + 1, pos.y + 1, pos.z]); } if (IsBitSet(edgeTable[cubeIndex], 2048)) { vertlist[11] = VertexInterp(isolevel, positions[3], positions[7], denses[3], denses[7], densityNormals[pos.x, pos.y, pos.z], densityNormals[pos.x, pos.y + 1, pos.z]); } int submesh = densities.getMaterial(pos.x, pos.y, pos.z); for (int i = 0; triTable[cubeIndex][i] != -1; i += 3) { submeshIDList.Add(submesh); subMeshTriCount[submesh] = subMeshTriCount[submesh] + 1; triangleList.Add(new Triangle(vertlist[triTable[cubeIndex][i]][0], vertlist[triTable[cubeIndex][i + 1]][0], vertlist[triTable[cubeIndex][i + 2]][0], vertlist[triTable[cubeIndex][i]][1], vertlist[triTable[cubeIndex][i + 1]][1], vertlist[triTable[cubeIndex][i + 2]][1])); } }
/// <summary> /// Called when the viewpoint has changed. /// </summary> /// <param name="pos"></param> public void viewPosChanged(Vector3 pos) { //float sep = 10f; //float distance = ((center.x - pos.x) * (center.x - pos.x) + //(center.y - pos.y) * (center.y - pos.y) + //(center.z - pos.z) * (center.z - pos.z)); //if (distance < (((float)NodeManager.LODRange[LOD]) * sep) * (((float)NodeManager.LODRange[LOD]) * sep)) Vector3I viewPos = NodeManager.viewChunkPos[LOD]; /*Debug.Log(viewPos+","+LOD); 如前所述,viewChunkPos其实应该是摄像机当前位置在各个细节层次上的V3I坐标值 这里根据LOD选择相应层次下面的对应V3I */ int size = 1; /*chunkPos是center的position在当前LOD下面的v3i坐标 下面的这个判定式就是说viewPos(摄像机位置V3I)是不是在当前chunk内部(中心+-1,这也是用V3I的好处) */ if ((viewPos.x >= chunkPos.x - size && viewPos.x <= chunkPos.x + size) && (viewPos.y >= chunkPos.y - size && viewPos.y <= chunkPos.y + size) && (viewPos.z >= chunkPos.z - size && viewPos.z <= chunkPos.z + size)) { if (isBottomLevel()) createSubNodes(RenderType.FRONT); for (int i = 0; i < 8; i++) { if (subNodes[i] != null) subNodes[i].viewPosChanged(pos); //向下传递命令 } } //else if (!permanent) else { size += 2; if (LOD < 3 && (viewPos.x < chunkPos.x - size || viewPos.x > chunkPos.x + size) || (viewPos.y < chunkPos.y - size || viewPos.y > chunkPos.y + size) || (viewPos.z < chunkPos.z - size || viewPos.z > chunkPos.z + size)) { /*Debug.Log(size+","+LOD+"viewPos:"+viewPos+","+chunkPos); 在lod低阶的时候,如果在一个半chunk以外,也就是包围当前chunk的chunks以外,那就不再subdivide的意思吧……*/ for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } else if (LOD >= 3) //在粗糙的层级,只要超出了当前chunk那就直接不再subdivide { for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } } if (LOD == 0) { /*Debug.Log("LOD 0 situation"); lod0的情况是经常会发生的*/ float nodeSize = (float)NodeManager.LODSize[0] * (float)NodeManager.nodeSize; /*Debug.Log(nodeSize); 仍旧是LODSize[0]是4,nodesize当然是16,这里nodesize是64*/ //其实下面这里是函数里面第一次用到pos进行运算,前面那个引用pos只是向下传递接过来的参数。 Vector3I viewChunk = new Vector3I((int)(pos.x / nodeSize), (int)(pos.y / nodeSize), (int)(pos.z / nodeSize)); /*if(!viewChunk.Equals(NodeManager.viewChunkPos[0])){ Debug.Log(viewChunk+",NM.viewChunkPos: "+NodeManager.viewChunkPos[0]); } 这两个真的不是一直都是相等的。好神奇。所以千万不要乱改。 因为确实nodeSize就是nodemanager里面nWidth在lod=0的值,那就只可能是两处的pos不一定一样了。 */ Vector3I curChunk = new Vector3I((int)(position.x / nodeSize), (int)(position.y / nodeSize), (int)(position.z / nodeSize)); if (curChunk.x >= viewChunk.x - 3 && curChunk.x <= viewChunk.x + 3 && curChunk.y >= viewChunk.y - 3 && curChunk.y <= viewChunk.y + 3 && curChunk.z >= viewChunk.z - 3 && curChunk.z <= viewChunk.z + 3) { //curChunk,viewChunk,viewPos,chunkPos,这个家伙命名还真是随意啊 //collides是一个什么鬼,当前摄像机位置在curChunk三个单位(其实是各个轴6个单位)以内时: collides = true; if (chunk != null) { chunk.GetComponent<MeshCollider>().sharedMesh = chunk.GetComponent<MeshFilter>().sharedMesh; } } } renderCheck(); }
/// <summary> /// Sets the density of a point, given a world pos. /// </summary> /// <param name="worldPos"></param> public void setDensityFromWorldPos(Vector3 worldPos, float val) { worldPos = worldPos - position; Vector3I arrayPos = new Vector3I((int)(worldPos.x), (int)(worldPos.y), (int)(worldPos.z)); if (arrayPos.x < -1 || arrayPos.x > 17 || arrayPos.y < -1 || arrayPos.y > 17 || arrayPos.z < -1 || arrayPos.z > 17) { //Debug.Log("Wrong node. " + arrayPos+", and worldPos is :"+worldPos); return; } densityChangeData.set(arrayPos.x, arrayPos.y, arrayPos.z, val); setPermanence(true); hasDensityChangeData = true; MeshFactory.requestSave(this); }
/// <summary> /// Sets the view position, and checks if chunks need to be updated /// </summary> /// <param name="pos"></param> public static void setViewPosition(Vector3 pos) { /*Debug.Log(pos+",cameraPos:"+QuixelEngine.getCameraPos()); 测试结果,这里的pos确实就是camera的位置 所以应该每次camera位置更新以后这里就会被call 然后计算出各个LOD下面camera的viewPosition(V3I形式) */ for (int i = 0; i <= maxLOD; i++) { float nWidth = LODSize[i] * nodeSize; viewChunkPos[i].x = (int)(pos.x / nWidth); viewChunkPos[i].y = (int)(pos.y / nWidth); viewChunkPos[i].z = (int)(pos.z / nWidth); } float sWidth = LODSize[0] * nodeSize * 0.5f; //不知是谁设置的,但是这里的LODSize[0]已经是4了,毕竟init的时候debug就是这样,所以这里sWidth是32 Vector3I newPos = new Vector3I((int)(pos.x / sWidth), (int)(pos.y / sWidth), (int)(pos.z / sWidth)); //getTopNode不管character怎么掉都一直是0,-1,0. //不过如果一开始很高的话(大于0?)这个时侯会是0,0,0 //然后curTopNode和getTopNode倒是一直都很一致 //这是因为下面的这一大长段内容,如果curTop和Top不一样的话就马上进行调整 //newPos是为了调整curBottomNode if (!curTopNode.Equals(getTopNode(pos))) { float nodeWidth = LODSize[maxLOD] * nodeSize; Vector3I diff = getTopNode(pos).Subtract(curTopNode); curTopNode = getTopNode(pos); while (diff.x > 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[0, y, z].dispose(); topNodes[0, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[2, y, z]; topNodes[2, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x--; } while (diff.x < 0) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { topNodes[2, y, z].dispose(); topNodes[2, y, z] = topNodes[1, y, z]; topNodes[1, y, z] = topNodes[0, y, z]; topNodes[0, y, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) - nodeWidth, (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.x++; } while (diff.y > 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 0, z].dispose(); topNodes[x, 0, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 2, z]; topNodes[x, 2, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y--; } while (diff.y < 0) { for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { topNodes[x, 2, z].dispose(); topNodes[x, 2, z] = topNodes[x, 1, z]; topNodes[x, 1, z] = topNodes[x, 0, z]; topNodes[x, 0, z] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) - nodeWidth, (curTopNode.z * nodeWidth) + ((z - 1) * nodeWidth)), 0, maxLOD, Node.RenderType.FRONT); } } diff.y++; } while (diff.z > 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 0].dispose(); topNodes[x, y, 0] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 2]; topNodes[x, y, 2] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) + nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z--; } while (diff.z < 0) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { topNodes[x, y, 2].dispose(); topNodes[x, y, 2] = topNodes[x, y, 1]; topNodes[x, y, 1] = topNodes[x, y, 0]; topNodes[x, y, 0] = new Node(null, new Vector3((curTopNode.x * nodeWidth) + ((x - 1) * nodeWidth), (curTopNode.y * nodeWidth) + ((y - 1) * nodeWidth), (curTopNode.z * nodeWidth) - nodeWidth), 0, maxLOD, Node.RenderType.FRONT); } } diff.z++; } } if (curBottomNode.x != newPos.x || curBottomNode.y != newPos.y || curBottomNode.z != newPos.z) { Vector3 setPos = new Vector3(newPos.x * sWidth + (sWidth / 1f), newPos.y * sWidth + (sWidth / 1f), newPos.z * sWidth + (sWidth / 1f)); for (int x = 0; x < 3; x++){ for (int y = 0; y < 3; y++){ for (int z = 0; z < 3; z++) { topNodes[x, y, z].viewPosChanged(setPos); //Debug.Log(setPos+",newpos:"+newPos+",curbuttom:"+curBottomNode); /* (32.0, -96.0, 32.0),newpos:(0,-4,0),curbuttom:(0,-3,0)>>(0,-4,0) */ }}} curBottomNode = newPos; } }
/// <summary> /// Sets the density value at the given coordinates. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <returns></returns> public void set(Vector3I pos, float val) { set(pos.x, pos.y, pos.z, val); }
/// <summary> /// Sets the material of the voxel at the given world position. /// </summary> /// <param name="worldPos"></param> /// <param name="val"></param> public void setMaterialFromWorldPos(Vector3 worldPos, byte val) { worldPos = worldPos - position; Vector3I arrayPos = new Vector3I((int)Math.Round(worldPos.x) / NodeManager.LODSize[LOD], (int)Math.Round(worldPos.y) / NodeManager.LODSize[LOD], (int)Math.Round(worldPos.z) / NodeManager.LODSize[LOD]); if (arrayPos.x < -1 || arrayPos.x > 17 || arrayPos.y < -1 || arrayPos.y > 17 || arrayPos.z < -1 || arrayPos.z > 17) { Debug.Log("Wrong node. " + arrayPos); return; } bool change = (densityChangeData.getMaterial(arrayPos.x, arrayPos.y, arrayPos.z) != val); densityChangeData.setMaterial(arrayPos.x, arrayPos.y, arrayPos.z, val); if (change) { setPermanence(true); hasDensityChangeData = true; MeshFactory.requestSave(this); } }
/// <summary> /// Adds another vector's values to this /// </summary> /// <param name="other"></param> /// <returns></returns> public Vector3I Add(Vector3I other) { return new Vector3I(x + other.x, y + other.y, z + other.z); }
/// <summary> /// Called when the viewpoint has changed. /// </summary> /// <param name="pos"></param> public void viewPosChanged(Vector3 pos) { //float sep = 10f; //float distance = ((center.x - pos.x) * (center.x - pos.x) + //(center.y - pos.y) * (center.y - pos.y) + //(center.z - pos.z) * (center.z - pos.z)); //if (distance < (((float)NodeManager.LODRange[LOD]) * sep) * (((float)NodeManager.LODRange[LOD]) * sep)) Vector3I viewPos = NodeManager.viewChunkPos[LOD]; int size = 1; if ((viewPos.x >= chunkPos.x - size && viewPos.x <= chunkPos.x + size) && (viewPos.y >= chunkPos.y - size && viewPos.y <= chunkPos.y + size) && (viewPos.z >= chunkPos.z - size && viewPos.z <= chunkPos.z + size)) { if (isBottomLevel()) createSubNodes(RenderType.FRONT); for (int i = 0; i < 8; i++) { if (subNodes[i] != null) subNodes[i].viewPosChanged(pos); } } //else if (!permanent) else { size += 2; if (LOD < 3 && (viewPos.x < chunkPos.x - size || viewPos.x > chunkPos.x + size) || (viewPos.y < chunkPos.y - size || viewPos.y > chunkPos.y + size) || (viewPos.z < chunkPos.z - size || viewPos.z > chunkPos.z + size)) { for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } else if (LOD >= 3) { for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } } if (LOD == 0) { float nodeSize = (float)NodeManager.LODSize[0] * (float)NodeManager.nodeSize; Vector3I viewChunk = new Vector3I((int)(pos.x / nodeSize), (int)(pos.y / nodeSize), (int)(pos.z / nodeSize)); Vector3I curChunk = new Vector3I((int)(position.x / nodeSize), (int)(position.y / nodeSize), (int)(position.z / nodeSize)); if (curChunk.x >= viewChunk.x - 3 && curChunk.x <= viewChunk.x + 3 && curChunk.y >= viewChunk.y - 3 && curChunk.y <= viewChunk.y + 3 && curChunk.z >= viewChunk.z - 3 && curChunk.z <= viewChunk.z + 3) { collides = true; if (chunk != null) { chunk.GetComponent<MeshCollider>().sharedMesh = chunk.GetComponent<MeshFilter>().sharedMesh; } } } renderCheck(); }
/// <summary> /// Returns a list of points inside of a given brush type and size. /// </summary> /// <param name="type"></param> /// <param name="size"></param> /// <param name="pos"></param> /// <returns></returns> private static List<Vector3> getPoints(BrushType type, int size, Vector3 pos) { float nodeWidth = NodeManager.LODSize[0]; Vector3I point = new Vector3I((int)Math.Round(pos.x / nodeWidth), (int)Math.Round(pos.y / nodeWidth), (int)Math.Round(pos.z / nodeWidth)); List<Vector3> ret = new List<Vector3>(); switch (type) { case BrushType.BOX: for (int x = 0; x <= size; x++) { for (int y = 0; y <= size; y++) { for (int z = 0; z <= size; z++) { Vector3 realPos = new Vector3(); realPos.x = ((point.x + x) * nodeWidth); realPos.y = ((point.y + y) * nodeWidth); realPos.z = ((point.z + z) * nodeWidth); ret.Add(realPos); } } } break; case BrushType.SPHERE: for (int x = -size; x < size; x++) { for (int y = -size * 2; y < size; y++) { for (int z = -size; z < size; z++) { Vector3 realPos = new Vector3(); realPos.x = ((point.x + x) * nodeWidth); realPos.y = ((point.y + y) * nodeWidth); realPos.z = ((point.z + z) * nodeWidth); if (Vector3.Distance(realPos, pos) < size * nodeWidth) { ret.Add(realPos); } } } } break; } return ret; }
/// <summary> /// Returns a 3d integer vector position of the "top" (highest LOD) node that contains the given position. /// </summary> /// <param name="pos"></param> /// <returns></returns> public static Vector3I getTopNode(Vector3 pos) { Vector3I ret = new Vector3I(); ret.x = (int)Mathf.Floor(pos.x / (NodeManager.LODSize[maxLOD] * nodeSize)); ret.y = (int)Mathf.Floor(pos.y / (NodeManager.LODSize[maxLOD] * nodeSize)); ret.z = (int)Mathf.Floor(pos.z / (NodeManager.LODSize[maxLOD] * nodeSize)); return ret; }
/// <summary> /// Calculates a density value given a location /// </summary> /// <param name="node"></param> /// <param name="pos"></param> /// <returns></returns> private static VoxelData calculateDensity(Node node, Vector3I pos) { int nodeWidth = NodeManager.LODSize[node.LOD]; Vector3 ws = new Vector3(node.position.x + (nodeWidth * pos.x), node.position.y + (nodeWidth * pos.y), node.position.z + (nodeWidth * pos.z)); return terrainGenerator.calculateDensity(ws); }
/// <summary> /// Initializes the node manager. /// </summary> public static void init(string worldName) { NodeManager.worldName = worldName; float nSize = LODSize[maxLOD] * nodeSize; for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { for (int z = -1; z < 2; z++) { topNodes[x + 1, y + 1, z + 1] = new Node(null, new Vector3(x * nSize, y * nSize, z * nSize), 0, maxLOD, Node.RenderType.FRONT); } } } viewChunkPos = new Vector3I[maxLOD + 1]; for (int i = 0; i <= maxLOD; i++) viewChunkPos[i] = new Vector3I(); }
/// <summary> /// Generates the triangles for a specific voxel /// </summary> /// <param name="node">The node that contains the voxel</param> /// <param name="pos">The voxel position (Not real position) [16,16,16]</param> /// <param name="triangleList">The list used to contain triangles made so far</param> /// <param name="densities">The array that contains density information</param> /// <param name="densityNormals">The array that contains density normals</param> private static void generateTriangles(Node node, Vector3I pos, List<Triangle> triangleList, List<int> submeshIDList, int[] subMeshTriCount, DensityData densities, Vector3[, ,] densityNormals) { float size = NodeManager.LODSize[node.LOD]; float[] denses = new float[8]; denses[0] = densities.get(pos.x, pos.y, pos.z + 1); denses[1] = densities.get(pos.x + 1, pos.y, pos.z + 1); denses[2] = densities.get(pos.x + 1, pos.y, pos.z); denses[3] = densities.get(pos.x, pos.y, pos.z); denses[4] = densities.get(pos.x, pos.y + 1, pos.z + 1); denses[5] = densities.get(pos.x + 1, pos.y + 1, pos.z + 1); denses[6] = densities.get(pos.x + 1, pos.y + 1, pos.z); denses[7] = densities.get(pos.x, pos.y + 1, pos.z); byte cubeIndex = 0; if (denses[0] < isolevel) cubeIndex |= 1; if (denses[1] < isolevel) cubeIndex |= 2; if (denses[2] < isolevel) cubeIndex |= 4; if (denses[3] < isolevel) cubeIndex |= 8; if (denses[4] < isolevel) cubeIndex |= 16; if (denses[5] < isolevel) cubeIndex |= 32; if (denses[6] < isolevel) cubeIndex |= 64; if (denses[7] < isolevel) cubeIndex |= 128; if (cubeIndex == 0 || cubeIndex == 255) return; Vector3 origin = new Vector3((size * (pos.x)) , (size * (pos.y)) , (size * (pos.z))); Vector3[] positions = new Vector3[8]; positions[0] = new Vector3(origin.x, origin.y, origin.z + size); positions[1] = new Vector3(origin.x + size, origin.y, origin.z + size); positions[2] = new Vector3(origin.x + size, origin.y, origin.z); positions[3] = new Vector3(origin.x, origin.y, origin.z); positions[4] = new Vector3(origin.x, origin.y + size, origin.z + size); positions[5] = new Vector3(origin.x + size, origin.y + size, origin.z + size); positions[6] = new Vector3(origin.x + size, origin.y + size, origin.z); positions[7] = new Vector3(origin.x, origin.y + size, origin.z); Vector3[][] vertlist = new Vector3[12][]; if (IsBitSet(edgeTable[cubeIndex], 1)) vertlist[0] = VertexInterp(isolevel, positions[0], positions[1], denses[0], denses[1], densityNormals[pos.x, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 2)) vertlist[1] = VertexInterp(isolevel, positions[1], positions[2], denses[1], denses[2], densityNormals[pos.x + 1, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y, pos.z]); if (IsBitSet(edgeTable[cubeIndex], 4)) vertlist[2] = VertexInterp(isolevel, positions[2], positions[3], denses[2], denses[3], densityNormals[pos.x + 1, pos.y, pos.z], densityNormals[pos.x, pos.y, pos.z]); if (IsBitSet(edgeTable[cubeIndex], 8)) vertlist[3] = VertexInterp(isolevel, positions[3], positions[0], denses[3], denses[0], densityNormals[pos.x, pos.y, pos.z], densityNormals[pos.x, pos.y, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 16)) vertlist[4] = VertexInterp(isolevel, positions[4], positions[5], denses[4], denses[5], densityNormals[pos.x, pos.y + 1, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 32)) vertlist[5] = VertexInterp(isolevel, positions[5], positions[6], denses[5], denses[6], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z]); if (IsBitSet(edgeTable[cubeIndex], 64)) vertlist[6] = VertexInterp(isolevel, positions[6], positions[7], denses[6], denses[7], densityNormals[pos.x + 1, pos.y + 1, pos.z], densityNormals[pos.x, pos.y + 1, pos.z]); if (IsBitSet(edgeTable[cubeIndex], 128)) vertlist[7] = VertexInterp(isolevel, positions[7], positions[4], denses[7], denses[4], densityNormals[pos.x, pos.y + 1, pos.z], densityNormals[pos.x, pos.y + 1, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 256)) vertlist[8] = VertexInterp(isolevel, positions[0], positions[4], denses[0], denses[4], densityNormals[pos.x, pos.y, pos.z + 1], densityNormals[pos.x, pos.y + 1, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 512)) vertlist[9] = VertexInterp(isolevel, positions[1], positions[5], denses[1], denses[5], densityNormals[pos.x + 1, pos.y, pos.z + 1], densityNormals[pos.x + 1, pos.y + 1, pos.z + 1]); if (IsBitSet(edgeTable[cubeIndex], 1024)) vertlist[10] = VertexInterp(isolevel, positions[2], positions[6], denses[2], denses[6], densityNormals[pos.x + 1, pos.y, pos.z], densityNormals[pos.x + 1, pos.y + 1, pos.z]); if (IsBitSet(edgeTable[cubeIndex], 2048)) vertlist[11] = VertexInterp(isolevel, positions[3], positions[7], denses[3], denses[7], densityNormals[pos.x, pos.y, pos.z], densityNormals[pos.x, pos.y + 1, pos.z]); int submesh = densities.getMaterial(pos.x, pos.y, pos.z); for (int i = 0; triTable[cubeIndex][i] != -1; i += 3) { submeshIDList.Add(submesh); subMeshTriCount[submesh] = subMeshTriCount[submesh] + 1; triangleList.Add(new Triangle(vertlist[triTable[cubeIndex][i]][0], vertlist[triTable[cubeIndex][i + 1]][0], vertlist[triTable[cubeIndex][i + 2]][0], vertlist[triTable[cubeIndex][i]][1], vertlist[triTable[cubeIndex][i + 1]][1], vertlist[triTable[cubeIndex][i + 2]][1])); } }
/// <summary> /// Called when the viewpoint has changed. /// </summary> /// <param name="pos"></param> public void viewPosChanged(Vector3 pos) { //float sep = 10f; //float distance = ((center.x - pos.x) * (center.x - pos.x) + //(center.y - pos.y) * (center.y - pos.y) + //(center.z - pos.z) * (center.z - pos.z)); //if (distance < (((float)NodeManager.LODRange[LOD]) * sep) * (((float)NodeManager.LODRange[LOD]) * sep)) Vector3I viewPos = NodeManager.viewChunkPos[LOD]; int size = 1; if ((viewPos.x >= chunkPos.x - size && viewPos.x <= chunkPos.x + size) && (viewPos.y >= chunkPos.y - size && viewPos.y <= chunkPos.y + size) && (viewPos.z >= chunkPos.z - size && viewPos.z <= chunkPos.z + size)) { if (isBottomLevel()) { createSubNodes(RenderType.FRONT); } for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].viewPosChanged(pos); } } } //else if (!permanent) else { size += 2; if (LOD < 3 && (viewPos.x < chunkPos.x - size || viewPos.x > chunkPos.x + size) || (viewPos.y < chunkPos.y - size || viewPos.y > chunkPos.y + size) || (viewPos.z < chunkPos.z - size || viewPos.z > chunkPos.z + size)) { for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } else if (LOD >= 3) { for (int i = 0; i < 8; i++) { if (subNodes[i] != null) { subNodes[i].dispose(); subNodes[i] = null; } } } } if (LOD == 0) { float nodeSize = (float)NodeManager.LODSize[0] * (float)NodeManager.nodeSize; Vector3I viewChunk = new Vector3I((int)(pos.x / nodeSize), (int)(pos.y / nodeSize), (int)(pos.z / nodeSize)); Vector3I curChunk = new Vector3I((int)(position.x / nodeSize), (int)(position.y / nodeSize), (int)(position.z / nodeSize)); if (curChunk.x >= viewChunk.x - 3 && curChunk.x <= viewChunk.x + 3 && curChunk.y >= viewChunk.y - 3 && curChunk.y <= viewChunk.y + 3 && curChunk.z >= viewChunk.z - 3 && curChunk.z <= viewChunk.z + 3) { collides = true; if (chunk != null) { chunk.GetComponent <MeshCollider>().sharedMesh = chunk.GetComponent <MeshFilter>().sharedMesh; } } } renderCheck(); }