private void GenerateSamples(int amount = 10) { meshCollider.sharedMesh = currentPointCloud.mesh.mesh; var camRay = camera.ScreenPointToRay(Input.mousePosition); var dir = camRay.direction; var(dist, _) = PolySurface.RayMarch(coefficients, camRay.origin, dir, 1000.0f, surface.Center); var hit = camRay.origin + (dist + 0.001f) * camRay.direction; hit = currentCenter - currentNormal * 0.001f; dir = -currentNormal; int count = 0; while (count < amount) { int stepCount = 0; var exit = TestDataGenerator.SimulatePath( samplesRandom, surface.Coefficients, hit, dir, surface.Center, surface.g, surface.SigmaSReduced, surface.sigmaT, distScale, null, ref stepCount); if (exit != null) { count += 1; var ray = new Ray(exit.Value, -PolySurface.GetNormalAt(surface.Coefficients, exit.Value, surface.Center)); if (autoProjectSamples && meshCollider.Raycast(ray, out var h, float.MaxValue)) { var go = GameObject.Instantiate(samplePointPrefab, transform); go.transform.position = h.point; samples.Add(go); //samples.Add(new MeshDBSample //{ // position = h.point, // gradient = -ray.direction, //}); } else { var go = GameObject.Instantiate(samplePointPrefab, transform); go.transform.position = exit.Value; samples.Add(go); //samples.Add(new MeshDBSample //{ // position = exit.Value, // gradient = -ray.direction //}); } } }
private void GetSamplesFromModel(Vector3 center, Vector3 normal, Vector3 direction) { Debug.Log("Start generator"); foreach (var go in samples) { GameObject.Destroy(go); } samples.Clear(); var coefficients = surface.Coefficients.ToArray(); var normalToZ = new Frame(normal); var zToDirection = new Frame(-direction).Invert(); TestDataGenerator.RotatePolynomial(coefficients, normalToZ.x, normalToZ.y, normalToZ.z); if (!incidentIsNormal) { TestDataGenerator.RotatePolynomial(coefficients, zToDirection.x, zToDirection.y, zToDirection.z); } string[] arguments = null; string fileExe = null; var model = string.IsNullOrWhiteSpace(modelVersion) ? $"{modelName}/final" : $"{modelName}/{modelVersion}"; switch (sampleSource) { case SampleSource.Cpp: fileExe = @"D:\Bachelorarbeit\CppModelTest\x64\Release\CppModelTest.exe"; arguments = new string[] { model, samplesToGenerate.ToString(), modelStddev.ToString(), $"{string.Join(",", coefficients)},{surface.alphaEff},{surface.g},{surface.ior}" }; break; case SampleSource.Python: fileExe = "python.exe"; arguments = new string[] { @"D:\Bachelorarbeit\Bachelorarbeit\Model\generate_samples.py", model, samplesToGenerate.ToString(), modelStddev.ToString(), $"{string.Join(",", coefficients)},{surface.alphaEff},{surface.g},{surface.ior}" }; break; default: fileExe = @"D:\Bachelorarbeit\CppModelTest\x64\Release\CppModelTest.exe"; arguments = new string[] { model, samplesToGenerate.ToString(), modelStddev.ToString(), $"{string.Join(",", coefficients)},{surface.alphaEff},{surface.g},{surface.ior}" }; break; } var p = new System.Diagnostics.Process(); p.StartInfo.FileName = fileExe; p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; p.StartInfo.WorkingDirectory = @"D:\Bachelorarbeit\Bachelorarbeit\Model"; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.Arguments = string.Join(" ", arguments.Select(a => $"\"{a}\"")); Debug.Log(p.StartInfo.Arguments); var r = new System.Random(); p.OutputDataReceived += (sender, args) => { if (args.Data != null && args.Data.StartsWith("# ")) { var parts = args.Data.Substring(2).Split(',').Select(s => float.Parse(s)).ToArray(); var pos = new Vector3(parts[0], parts[1], parts[2]); var n = PolySurface.GetNormalAt(coefficients, pos, Vector3.zero); //pos = new Vector3(0, 0, (float)r.NextDouble()); if (!incidentIsNormal) { pos = zToDirection.ToMatrix() * pos; n = zToDirection.ToMatrix() * n; } pos = normalToZ.ToMatrix() * pos; n = normalToZ.ToMatrix() * n; pos += center; samplesTemp.Add(new MeshDBSample { position = pos, gradient = n }); } }; p.Start(); p.BeginOutputReadLine(); process = p; }
public static Vector3?SimulatePath(System.Random random, float[] coefficients, Vector3 origin, Vector3 direction, Vector3 center, float g, float sigmaSRed, float sigmaA, float distScale, Action <PathPoint> onInteraction, ref int stepCount) { direction = direction.normalized; float maxDist = float.MaxValue; maxDist = GetScatterDistance(random, sigmaSRed) * distScale; float throughput = 1.0f; for (int i = 0; i < 500; i++) { stepCount += 1; var(dist, inside) = PolySurface.RayMarch(coefficients, origin, direction, maxDist, center); var newPoint = origin + direction * dist; var point = new PathPoint { position = newPoint, direction = direction }; var normal = PolySurface.GetNormalAt(coefficients, newPoint, center); origin = newPoint - normal * PolySurface.SURF_DIST * 2; if (!inside) { // exited surface return(newPoint); } direction = GetRandomNewDirection(random, g, direction); // still inside, set random direction and maxDist //if (g == 0) { // direction = OnUnitSphere(random); //} else { // float rand = RandomRange(random, 0.0f, 1.0f); // float cosAngle = InvIntPhaseFunction(rand, g); // float theta = Mathf.Acos(cosAngle); // float d = 1 / Mathf.Tan(theta); // // Debug.Log($"rand: {rand}, cosAngle: {cosAngle}, theta: {theta}, d: {d}"); // if (d == float.PositiveInfinity) { // // do nothing // //direction = direction; // } else if (d == float.NegativeInfinity) { // direction = -direction; // } else { // var right = GetPerpendicular(direction).normalized; // var up = Vector3.Cross(right, direction).normalized; // var uv = InsideUnitCircle(random); // point.uv = uv; // point.right = right; // point.up = up; // // Debug.Log($"right: {right}, up: {up}, uv: {uv}"); // direction = uv.x * right + uv.y * up + d * direction; // direction = direction.normalized; // } //} // Debug.Log($"direction: {direction}"); maxDist = GetScatterDistance(random, sigmaSRed) * distScale; point.direction = point.direction * Vector3.Dot(point.direction, direction * maxDist); onInteraction?.Invoke(point); float transmission = Mathf.Exp(-sigmaA * maxDist); throughput = throughput * transmission; // russian roulette if (i > 5) { if ((float)random.NextDouble() > throughput) { return(null); } throughput = 1; } } // reached max steps, ray counts as absorbed return(null); }