public static RayTraceResult rayTrace(Vector3 startPos, Vector3 dir, RayTraceChunkManager rtm, float length) { DirInfo dirInfo = new DirInfo(dir); Vector3 startPosInner = startPos; float hitTime = 0; float startOffset = 0; bool bHitBounds = true;//能击中总区域,或者在内部 if (startPos.x >= 0 && startPos.x < rtm.getSizeX() && startPos.y >= 0 && startPos.y < rtm.getSizeY() && startPos.z >= 0 && startPos.z < rtm.getSizeZ()) { bHitBounds = true; } else { bHitBounds = Misc.rayHitAABB(startPos, dir, new Vector3(0, 0, 0), rtm.getSize(), ref hitTime); if (hitTime > 0) { startOffset = hitTime; } startPosInner = startPos + dir * startOffset - dir * 0.01f; } if (bHitBounds) { RayTraceResult rlt = rayTraceSmall(startPosInner, dirInfo, rtm, Face.FNI_Unknown, length - startOffset); rlt.hitLength += startOffset; return(rlt); } else { return(new RayTraceResult(false, 0, 0, 0, Face.FNI_Unknown, 0)); } }
public static Color[] ToColorsA(RayTraceChunkManager rtc, int bits) { int dcx = rtc.getChunkSize().x; int dcy = rtc.getChunkSize().y; int dcz = rtc.getChunkSize().z; int dgx = rtc.getSizeX(); int dgy = rtc.getSizeY(); int dgz = rtc.getSizeZ(); Color[,,] colors = new Color[dgx, (dgy / bits), dgz]; for (int cx = 0; cx < dcx; cx++) { for (int cy = 0; cy < dcy; cy++) { for (int cz = 0; cz < dcz; cz++) { RayTraceChunk chunk = rtc.getChunk(cx, cy, cz); for (int bx = 0; bx < Const.ChunkSize; bx++) { for (int by = 0; by < Const.ChunkSize / bits; by++) { for (int bz = 0; bz < Const.ChunkSize; bz++) { int iv = 0; for (int n = 0; n < bits; n++) { iv |= chunk.testBlock(bx, by * bits + n, bz) ? (1 << n) : 0; } float a = iv / (float)((1 << bits) - 1); int gx = cx * Const.ChunkSize + bx; int gy = cy * Const.ChunkSize / bits + by; int gz = cz * Const.ChunkSize + bz; colors[gx, gy, gz] = new Color(0, 0, 0, a); } } } } } } int sizeX = colors.GetLength(0); int sizeY = colors.GetLength(1); int sizeZ = colors.GetLength(2); Color[] rlt = new Color[sizeX * sizeY * sizeZ]; for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { rlt[z * sizeY * sizeX + y * sizeX + x] = colors[x, y, z]; } } } return(rlt); }
private static Texture3D Create3DTexture(RayTraceChunkManager rtc) { Texture3D voxelTexture = new Texture3D(rtc.getSizeX(), rtc.getSizeY() / 8, rtc.getSizeZ(), TextureFormat.Alpha8, false); voxelTexture.filterMode = FilterMode.Point; voxelTexture.wrapMode = TextureWrapMode.Clamp; voxelTexture.SetPixels(ToColorsA(rtc, 8)); voxelTexture.Apply(); return(voxelTexture); }
public void Init(RayTraceChunkManager rtc) { constValueTexture = CreateConstValueTexture(); texVoxel3D = Create3DTexture(rtc); calcAoMaterial = new Material(Shader.Find("Hidden/RaytraceAo")); }
public static RayTraceResult rayTraceSmall(Vector3 startPos, DirInfo dirInfo, RayTraceChunkManager rtm, Face faceIn, float maxLength) { int X = (int)(startPos.x + dirInfo.stepX * 0.0001f); int Y = (int)(startPos.y + dirInfo.stepY * 0.0001f); int Z = (int)(startPos.z + dirInfo.stepZ * 0.0001f); float tMaxX = (dirInfo.stepX > 0 ? (1 - (startPos.x - X)) : (startPos.x - X)) * dirInfo.tDeltaX;//沿射线走多远才能跳到下一个X格 float tMaxY = (dirInfo.stepY > 0 ? (1 - (startPos.y - Y)) : (startPos.y - Y)) * dirInfo.tDeltaY; float tMaxZ = (dirInfo.stepZ > 0 ? (1 - (startPos.z - Z)) : (startPos.z - Z)) * dirInfo.tDeltaZ; int outSizeX = dirInfo.stepX > 0 ? rtm.getSizeX() : -1; int outSizeY = dirInfo.stepY > 0 ? rtm.getSizeY() : -1; int outSizeZ = dirInfo.stepZ > 0 ? rtm.getSizeZ() : -1; while (true) { if (tMaxX < tMaxY) { if (tMaxX < tMaxZ) { X += dirInfo.stepX; if (X == outSizeX) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepX > 0 ? Face.FNI_x0 : Face.FNI_x1, tMaxX)); } else { if (tMaxX > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxX)); } else if (rtm.testBlock(X, Y, Z)) { return(new RayTraceResult(true, X, Y, Z, dirInfo.stepX > 0 ? Face.FNI_x0 : Face.FNI_x1, tMaxX)); } } tMaxX += dirInfo.tDeltaX; } else { Z += dirInfo.stepZ; if (Z == outSizeZ) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } else { if (tMaxZ > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxZ)); } else if (rtm.testBlock(X, Y, Z)) { return(new RayTraceResult(true, X, Y, Z, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } } tMaxZ += dirInfo.tDeltaZ; } } else { if (tMaxY < tMaxZ) { Y += dirInfo.stepY; if (Y == outSizeY) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepY > 0 ? Face.FNI_y0 : Face.FNI_y1, tMaxY)); } else { if (tMaxY > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxY)); } else if (rtm.testBlock(X, Y, Z)) { return(new RayTraceResult(true, X, Y, Z, dirInfo.stepY > 0 ? Face.FNI_y0 : Face.FNI_y1, tMaxY)); } } tMaxY += dirInfo.tDeltaY; } else { Z += dirInfo.stepZ; if (Z == outSizeZ) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } else { if (tMaxZ > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxZ)); } else if (rtm.testBlock(X, Y, Z)) { return(new RayTraceResult(true, X, Y, Z, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } } tMaxZ += dirInfo.tDeltaZ; } } } }
public static RayTraceResult rayTraceBig(Vector3 startPos, DirInfo dirInfo, RayTraceChunkManager rtm, Face faceIn, float maxLength) { int S = rtm.ChunkSize; int CX = (int)(startPos.x + dirInfo.stepX * 0.0001f) / S; int CY = (int)(startPos.y + dirInfo.stepY * 0.0001f) / S; int CZ = (int)(startPos.z + dirInfo.stepZ * 0.0001f) / S; int X = CX * S; int Y = CY * S; int Z = CZ * S; float curDistance = 0; float tMaxX = (dirInfo.stepX > 0 ? (S - (startPos.x - X)) : (startPos.x - X)) * dirInfo.tDeltaX;//沿射线走多远才能跳到下一个X格 float tMaxY = (dirInfo.stepY > 0 ? (S - (startPos.y - Y)) : (startPos.y - Y)) * dirInfo.tDeltaY; float tMaxZ = (dirInfo.stepZ > 0 ? (S - (startPos.z - Z)) : (startPos.z - Z)) * dirInfo.tDeltaZ; int outSizeCX = dirInfo.stepX > 0 ? rtm.getSizeX() / S : -1; int outSizeCY = dirInfo.stepY > 0 ? rtm.getSizeY() / S : -1; int outSizeCZ = dirInfo.stepZ > 0 ? rtm.getSizeZ() / S : -1; while (true) { if (tMaxX < tMaxY) { if (tMaxX < tMaxZ) { if (!rtm.isChunkEmpty(CX, CY, CZ)) { RayTraceResult smallRlt = rayTraceSmall(startPos + dirInfo.dir * curDistance, dirInfo, rtm, faceIn, Mathf.Max(tMaxX, maxLength) - curDistance); if (smallRlt.bHit) { smallRlt.hitLength += curDistance; return(smallRlt); } } CX += dirInfo.stepX; if (CX == outSizeCX) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepX > 0 ? Face.FNI_x0 : Face.FNI_x1, tMaxX)); } else { if (tMaxX > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxX)); } } curDistance = tMaxX; tMaxX += dirInfo.tDeltaX * S; } else { if (!rtm.isChunkEmpty(CX, CY, CZ)) { RayTraceResult smallRlt = rayTraceSmall(startPos + dirInfo.dir * curDistance, dirInfo, rtm, faceIn, Mathf.Max(tMaxZ, maxLength) - curDistance); if (smallRlt.bHit) { smallRlt.hitLength += curDistance; return(smallRlt); } } CZ += dirInfo.stepZ; if (CZ == outSizeCZ) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } else { if (tMaxZ > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxZ)); } } curDistance = tMaxZ; tMaxZ += dirInfo.tDeltaZ * S; } } else { if (tMaxY < tMaxZ) { if (!rtm.isChunkEmpty(CX, CY, CZ)) { RayTraceResult smallRlt = rayTraceSmall(startPos + dirInfo.dir * curDistance, dirInfo, rtm, faceIn, Mathf.Max(tMaxY, maxLength) - curDistance); if (smallRlt.bHit) { smallRlt.hitLength += curDistance; return(smallRlt); } } CY += dirInfo.stepY; if (CY == outSizeCY) { return(new RayTraceResult(false, X, Y, Z, dirInfo.stepY > 0 ? Face.FNI_y0 : Face.FNI_y1, tMaxY)); } else { if (tMaxY > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxY)); } } curDistance = tMaxY; tMaxY += dirInfo.tDeltaY * S; } else { if (!rtm.isChunkEmpty(CX, CY, CZ)) { RayTraceResult smallRlt = rayTraceSmall(startPos + dirInfo.dir * curDistance, dirInfo, rtm, faceIn, Mathf.Max(tMaxZ, maxLength) - curDistance); if (smallRlt.bHit) { smallRlt.hitLength += curDistance; return(smallRlt); } } CZ += dirInfo.stepZ; if (CZ == outSizeCZ) { return(new RayTraceResult(false, X, Y, X, dirInfo.stepZ > 0 ? Face.FNI_z0 : Face.FNI_z1, tMaxZ)); } else { if (tMaxZ > maxLength) { return(new RayTraceResult(false, X, Y, Z, Face.FNI_OutOfLength, tMaxZ)); } } curDistance = tMaxZ; tMaxZ += dirInfo.tDeltaZ * S; } } } }