// Perform signed sphere marching // Returns hitType 0, 1, 2, or 3 and update hit position/normal int RayMarching(Vector origin, Vector direction, float accuracy, out Vector hitPos, out Vector hitNorm) { float[,,] data = chacheData.GetDataDist(direction); hitPos = origin; hitNorm = direction; int hitType = (int)HitType.HIT_NONE; int noHitCount = 0; float d = chacheData.FastFastQueryDatabase(hitPos, data); // distance from closest object in world. float prev_d; //bool outside = false; // Signed distance marching for (float total_d = d; total_d < 100; total_d += d) { //Vec prev = hitPos; hitPos = origin + direction * total_d; prev_d = d; d = chacheData.FastFastQueryDatabase(hitPos, data); //if (prev_d >= accuracy + 0.01 && d < accuracy//тут было 0.01 if (d < accuracy ||//тут было 0.01 ++noHitCount > 99 || d < 0) { hitType = chacheData.FastFastQueryDatabaseHitType(hitPos); if (noHitCount < 99) { if (hitType == (int)HitType.HIT_LETTER) { d = scene.QueryDatabase(hitPos, out _); hitNorm = new Vector(scene.QueryDatabase(hitPos + new Vector(.01f, 0), out _) - d, scene.QueryDatabase(hitPos + new Vector(0, .01f), out _) - d, scene.QueryDatabase(hitPos + new Vector(0, 0, .01f), out _) - d).Normal(); //hitNorm = chacheData.FastFastQueryDatabaseNorm(hitPos); } else { hitNorm = chacheData.FastFastQueryDatabaseNorm(hitPos); //hitNorm = new Vec(chacheData.FastFastQueryDatabase(hitPos + new Vec(.01f, 0)) - d, // chacheData.FastFastQueryDatabase(hitPos + new Vec(0, .01f)) - d, // chacheData.FastFastQueryDatabase(hitPos + new Vec(0, 0, .01f)) - d).Normal(); } } if (float.IsNaN(hitNorm.x)) { //hitNorm = hitNorm; hitNorm = direction; } //hitPos = prev; //hitPos = (direction%hitNorm) return(hitType); // Weird return statement where a variable is also updated. } } return(0); }
public void InitData() { dataDist = new float[cx + 1, cy + 1, cz + 1]; dataDistPPP = new float[cx + 1, cy + 1, cz + 1]; dataDistPPM = new float[cx + 1, cy + 1, cz + 1]; dataDistPMP = new float[cx + 1, cy + 1, cz + 1]; dataDistPMM = new float[cx + 1, cy + 1, cz + 1]; dataDistMPP = new float[cx + 1, cy + 1, cz + 1]; dataDistMPM = new float[cx + 1, cy + 1, cz + 1]; dataDistMMP = new float[cx + 1, cy + 1, cz + 1]; dataDistMMM = new float[cx + 1, cy + 1, cz + 1]; dataType = new IMaterial[cx + 1, cy + 1, cz + 1]; dataNormal = new Vector[cx + 1, cy + 1, cz + 1]; float cellSizeX = (maxX - minX - 1) / cx; float cellSizeY = (maxY - minY - 1) / cy; float cellSizeZ = (maxZ - minZ - 1) / cz; diag = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY + cellSizeZ * cellSizeZ); for (int i = 0; i < cx; i++) { for (int j = 0; j < cy + 1; j++) { for (int k = 0; k < cz + 1; k++) { float worldX = minX + i * (maxX - minX - 1) / cx; float worldY = minY + j * (maxY - minY - 1) / cy; float worldZ = minZ + k * (maxZ - minZ - 1) / cz; Vector hitPos = new Vector(worldX, worldY, worldZ); float d = scene.QueryDatabase(hitPos, out var hitObj); dataDist[i, j, k] = d; dataType[i, j, k] = hitObj.Material; dataNormal[i, j, k] = scene.QueryDatabaseNorm(hitPos, d, hitObj); if (float.IsNaN(dataNormal[i, j, k].x)) { dataNormal[i, j, k] = new Vector(0, 0, 1); } } } } float diagXYZ = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY + cellSizeZ * cellSizeZ); float diagXY = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY); float diagXZ = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeZ * cellSizeZ); float diagYZ = (float)Math.Sqrt(cellSizeY * cellSizeY + cellSizeZ * cellSizeZ); for (int x = 1; x < cx; x++) { for (int y = 1; y < cy; y++) { for (int z = 1; z < cz; z++) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y <= 0 && normal.z <= 0)) { startMin = float.MaxValue; } dataDistMMM[x, y, z] = min(startMin, dataDistMMM[x - 1, y, z] + cellSizeX, dataDistMMM[x, y - 1, z] + cellSizeY, dataDistMMM[x, y, z - 1] + cellSizeZ, dataDistMMM[x - 1, y - 1, z] + diagXY, dataDistMMM[x, y - 1, z - 1] + diagYZ, dataDistMMM[x - 1, y, z - 1] + diagXZ, dataDistMMM[x - 1, y - 1, z - 1] + diagXYZ); } } } for (int x = 1; x < cx; x++) { for (int y = 1; y < cy; y++) { for (int z = cz - 1; z >= 0; z--) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y <= 0 && normal.z >= 0)) { startMin = float.MaxValue; } dataDistMMP[x, y, z] = min(startMin, dataDistMMP[x - 1, y, z] + cellSizeX, dataDistMMP[x, y - 1, z] + cellSizeY, dataDistMMP[x, y, z + 1] + cellSizeZ, dataDistMMP[x - 1, y - 1, z] + diagXY, dataDistMMP[x, y - 1, z + 1] + diagYZ, dataDistMMP[x - 1, y, z + 1] + diagXZ, dataDistMMP[x - 1, y - 1, z + 1] + diagXYZ); } } } for (int x = 1; x < cx; x++) { for (int y = cy - 1; y >= 0; y--) { for (int z = 1; z < cz; z++) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y >= 0 && normal.z <= 0)) { startMin = float.MaxValue; } dataDistMPM[x, y, z] = min(startMin, dataDistMPM[x - 1, y, z] + cellSizeX, dataDistMPM[x, y + 1, z] + cellSizeY, dataDistMPM[x, y, z - 1] + cellSizeZ, dataDistMPM[x - 1, y + 1, z] + diagXY, dataDistMPM[x, y + 1, z - 1] + diagYZ, dataDistMPM[x - 1, y, z - 1] + diagXZ, dataDistMPM[x - 1, y + 1, z - 1] + diagXYZ); } } } for (int x = 1; x < cx; x++) { for (int y = cy - 1; y >= 0; y--) { for (int z = cz - 1; z >= 0; z--) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y >= 0 && normal.z >= 0)) { startMin = float.MaxValue; } dataDistMPP[x, y, z] = min(startMin, dataDistMPP[x - 1, y, z] + cellSizeX, dataDistMPP[x, y + 1, z] + cellSizeY, dataDistMPP[x, y, z + 1] + cellSizeZ, dataDistMPP[x - 1, y + 1, z] + diagXY, dataDistMPP[x, y + 1, z + 1] + diagYZ, dataDistMPP[x - 1, y, z + 1] + diagXZ, dataDistMPP[x - 1, y + 1, z + 1] + diagXYZ); } } } for (int x = cx - 1; x >= 0; x--) { for (int y = 1; y < cy; y++) { for (int z = 1; z < cz; z++) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y <= 0 && normal.z <= 0)) { startMin = float.MaxValue; } dataDistPMM[x, y, z] = min(startMin, dataDistPMM[x + 1, y, z] + cellSizeX, dataDistPMM[x, y - 1, z] + cellSizeY, dataDistPMM[x, y, z - 1] + cellSizeZ, dataDistPMM[x + 1, y - 1, z] + diagXY, dataDistPMM[x, y - 1, z - 1] + diagYZ, dataDistPMM[x + 1, y, z - 1] + diagXZ, dataDistPMM[x + 1, y - 1, z - 1] + diagXYZ); } } } for (int x = cx - 1; x >= 0; x--) { for (int y = 1; y < cy; y++) { for (int z = cz - 1; z >= 0; z--) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y <= 0 && normal.z >= 0)) { startMin = float.MaxValue; } dataDistPMP[x, y, z] = min(startMin, dataDistPMP[x + 1, y, z] + cellSizeX, dataDistPMP[x, y - 1, z] + cellSizeY, dataDistPMP[x, y, z + 1] + cellSizeZ, dataDistPMP[x + 1, y - 1, z] + diagXY, dataDistPMP[x, y - 1, z + 1] + diagYZ, dataDistPMP[x + 1, y, z + 1] + diagXZ, dataDistPMP[x + 1, y - 1, z + 1] + diagXYZ); } } } for (int x = cx - 1; x >= 0; x--) { for (int y = cy - 1; y >= 0; y--) { for (int z = 1; z < cz; z++) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y >= 0 && normal.z <= 0)) { startMin = float.MaxValue; } dataDistPPM[x, y, z] = min(startMin, dataDistPPM[x + 1, y, z] + cellSizeX, dataDistPPM[x, y + 1, z] + cellSizeY, dataDistPPM[x, y, z - 1] + cellSizeZ, dataDistPPM[x + 1, y + 1, z] + diagXY, dataDistPPM[x, y + 1, z - 1] + diagYZ, dataDistPPM[x + 1, y, z - 1] + diagXZ, dataDistPPM[x + 1, y + 1, z - 1] + diagXYZ); } } } for (int x = cx - 1; x >= 0; x--) { for (int y = cy - 1; y >= 0; y--) { for (int z = cz - 1; z >= 0; z--) { float startMin = dataDist[x, y, z]; Vector normal = dataNormal[x, y, z]; if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y >= 0 && normal.z >= 0)) { startMin = float.MaxValue; } dataDistPPP[x, y, z] = min(startMin, dataDistPPP[x + 1, y, z] + cellSizeX, dataDistPPP[x, y + 1, z] + cellSizeY, dataDistPPP[x, y, z + 1] + cellSizeZ, dataDistPPP[x + 1, y + 1, z] + diagXY, dataDistPPP[x, y + 1, z + 1] + diagYZ, dataDistPPP[x + 1, y, z + 1] + diagXZ, dataDistPPP[x + 1, y + 1, z + 1] + diagXYZ); } } } }