public TransportPathTempVertex(float fromFirstStop, float toLastStop, float fromPrevious, PathVertex v) { MoveTimeFromFirstStop = fromFirstStop; MoveTimeToLastStop = toLastStop; MoveTimeFromPrevious = fromPrevious; Vertex = v; }
private Mesh <TriangleVertexData> CreateMesh() { var Points = new PathVertex[9] { new PathVertex(84, 84), new PathVertex(107, 83), new PathVertex(128, 169), new PathVertex(161, 222), new PathVertex(152, 236), new PathVertex(125, 237), new PathVertex(94, 183), new PathVertex(95, 126), new PathVertex(138, 208) }; var Indices = new int[21] { 0, 1, 2, 2, 6, 7, 0, 2, 7, 4, 6, 8, 4, 5, 6, 2, 6, 8, 3, 4, 8 }; return(new Mesh <TriangleVertexData>(Points, Indices)); }
Path CreateRestrictionPathCeiling() { const int OffsetY = 10; var Points = new PathVertex[10]; Points[0] = new PathVertex(663, 33 + OffsetY); Points[1] = new PathVertex(641 - 50, 18 + OffsetY); Points[2] = new PathVertex(650 - 40, 3 + OffsetY); Points[3] = new PathVertex(1055, 3 + OffsetY); Points[4] = new PathVertex(951, 23 + OffsetY); Points[5] = new PathVertex(886, 21 + OffsetY); Points[6] = new PathVertex(867, 32 + OffsetY); Points[7] = new PathVertex(848, 4 + OffsetY); Points[8] = new PathVertex(862, 15 + OffsetY); Points[9] = new PathVertex(877, 3 + OffsetY); int[] Indices = new int[24]; Indices[0] = 0; Indices[1] = 1; Indices[2] = 2; Indices[3] = 3; Indices[4] = 4; Indices[5] = 5; Indices[6] = 5; Indices[7] = 6; Indices[8] = 8; Indices[9] = 2; Indices[10] = 7; Indices[11] = 8; Indices[12] = 0; Indices[13] = 2; Indices[14] = 6; Indices[15] = 2; Indices[16] = 6; Indices[17] = 8; Indices[18] = 5; Indices[19] = 8; Indices[20] = 9; Indices[21] = 3; Indices[22] = 5; Indices[23] = 9; return(new Path(Points, Indices, 0.6f, 0.9f)); }
Path CreateRestrictionPathFloor() { var Points = new PathVertex[12]; Points[0] = new PathVertex(181, 248); Points[1] = new PathVertex(109, 348); Points[2] = new PathVertex(282, 396); Points[3] = new PathVertex(872, 392); Points[4] = new PathVertex(1042, 347); Points[5] = new PathVertex(983, 278); Points[6] = new PathVertex(814, 276); Points[7] = new PathVertex(791, 256); Points[8] = new PathVertex(660, 252); Points[9] = new PathVertex(650, 274); Points[10] = new PathVertex(387, 278); Points[11] = new PathVertex(358, 248); var Indices = new int[30]; Indices[0] = 0; Indices[1] = 1; Indices[2] = 2; Indices[3] = 2; Indices[4] = 3; Indices[5] = 4; Indices[6] = 2; Indices[7] = 4; Indices[8] = 5; Indices[9] = 2; Indices[10] = 5; Indices[11] = 6; Indices[12] = 2; Indices[13] = 6; Indices[14] = 9; Indices[15] = 2; Indices[16] = 10; Indices[17] = 11; Indices[18] = 0; Indices[19] = 2; Indices[20] = 11; Indices[21] = 2; Indices[22] = 9; Indices[23] = 10; Indices[24] = 7; Indices[25] = 8; Indices[26] = 9; Indices[27] = 6; Indices[28] = 7; Indices[29] = 9; return(new Path(Points, Indices, 1.0f, 0.6f)); }
/// <summary> /// 오픈 리스트에 더하기 전, /// 몇가지 사항들을 비교함 /// </summary> /// <param name="target"></param> void AddinOpenList(PathVertex target) { foreach (var vertex in _closeList) { if (target.myTilePos.Equals(vertex.myTilePos)) { return; } } foreach (var vertex in _openList) { if (target.myTilePos.Equals(vertex.myTilePos)) { if (vertex.Coast > target.Coast) { _openList.Remove(vertex); _openList.Add(target); return; } } } _openList.Add(target); }
private Mesh <TriangleVertexData> CreateMesh() { var Points = new PathVertex[11] { new PathVertex(539, 0), new PathVertex(528, 34), new PathVertex(529, 61), new PathVertex(572, 60), new PathVertex(576, 50), new PathVertex(648, 56), new PathVertex(650, 41), new PathVertex(580, 38), new PathVertex(588, 15), new PathVertex(601, 15), new PathVertex(607, 0) }; var Indices = new int[27] { 0, 8, 10, 8, 9, 10, 0, 1, 8, 1, 7, 8, 1, 2, 7, 2, 4, 7, 2, 3, 4, 5, 6, 7, 4, 5, 7 }; return(new Mesh <TriangleVertexData>(Points, Indices)); }
void AddOpenList(PathVertex newVertex) { if (closeList.ContainsKey(newVertex.X * 1000 + newVertex.Y)) { return; } openList.Add(newVertex); newVertex.myTilePos.AddedOpenList(); }
private void reset() { VisibilityGraphGenerator.removePathVertex(destination); destination = Terrain.getValidSquare(); goal.transform.position = destination.pos; VisibilityGraphGenerator.addPathVertex(destination); // canReachGoal = canReachDestination(); walkToNearbyNeighbor = false; setPathPlan(); i = 0; }
public void GatherLightPdfs(PathVertex lightVertex, int lastCameraVertexIdx, int numPdfs) { var nextVert = lightVertex; for (int i = lastCameraVertexIdx + 1; i < numPdfs - 2; ++i) { PdfsLightToCamera[i] = nextVert.PdfFromAncestor; PdfsCameraToLight[i + 2] = nextVert.PdfReverseAncestor + nextVert.PdfNextEventAncestor; nextVert = LightPathCache[nextVert.PathId, nextVert.AncestorId]; } PdfsLightToCamera[^ 2] = nextVert.PdfFromAncestor;
//for initialization public void SetNextVertex(PathVertex nextPathVertex) { nextVertex = nextPathVertex; segment = nextVertex.Position - transform.position; segment.y = 0; transform.forward = segment.normalized; magnitude = segment.magnitude; unitVector = segment.normalized; }
/// <summary>Send character down the next leg of a multi-hop trip.</summary> internal static void ContinueFlight(Unit unit) { if (unit.LatestTaxiPathNode == null) { return; } PathVertex pathVertex = unit.LatestTaxiPathNode.Value; PathNode to = pathVertex.Path.To; if (unit.m_TaxiMovementTimer.IsRunning && !unit.IsInRadius(to.Position, AirSpeed)) { return; } bool flag = false; if (unit.TaxiPaths.Count < 2) { flag = true; } else { if (unit.TaxiPaths.Dequeue().To != to) { unit.CancelTaxiFlight(); return; } TaxiPath taxiPath = unit.TaxiPaths.Peek(); if (to != taxiPath.From) { unit.CancelTaxiFlight(); return; } } if (!flag) { FlyUnit(unit, false); } else { if (IsNormalSpeed) { unit.Map.MoveObject(unit, pathVertex.Pos); } else { unit.TeleportTo(pathVertex.Pos); } unit.CancelTaxiFlight(); } }
// in python we would've simply used a priority dictionary, but C# doesn't really have it // so we need to implement a bunch of stuff by ourselves private PathVertex getVertexWithSmallestFCost(List <PathVertex> list) { // standard "get min from array" algorithm PathVertex min = list[0]; foreach (PathVertex v in list) { if (v.fCost < min.fCost) { min = v; } } return(min); }
float H = 0f; // 모든 장애물을 무시하고 목적지까지 가는 데 걸리는 거리 public PathVertex(PathVertex prevVertex, Vector2 curPos, Vector2 endPos) { curTilePos = curPos; _prevVertex = prevVertex; if (prevVertex == null) { G = 1; } else { G = prevVertex.G + 1; } H = Mathf.Abs(endPos.x - curPos.x) + Mathf.Abs(endPos.y - curPos.y); F = G + H; }
Mesh <TriangleVertexData> CreateCarpetMesh() { var Points = new PathVertex[4] { new PathVertex(155, 341), new PathVertex(373, 342), new PathVertex(382, 251), new PathVertex(216, 250) }; var Indices = new int[6] { 0, 1, 3, 1, 2, 3 }; return(new Mesh <TriangleVertexData>(Points, Indices)); }
public static Path CreateRectangularPath(int size) { var Points = new PathVertex[4]; Points[0] = new PathVertex(0, 0); Points[1] = new PathVertex(0, size); Points[2] = new PathVertex(size, 0); Points[3] = new PathVertex(size, size); var Indices = new int[6]; Indices[0] = 0; Indices[1] = 1; Indices[2] = 3; Indices[3] = 1; Indices[4] = 2; Indices[5] = 3; return(new Path(Points, Indices, 1.0f, 1.0f)); }
// spawns agent and their destination square and gives the destination square to the agent void spawnAgents() { while (numberOfAgents-- > 0) { Vector3 spawnPoint = Terrain.getValidSquare().pos; Agent tempAgent = Instantiate(agentPrefab, spawnPoint, Quaternion.identity); PathVertex destinationPoint = Terrain.getValidSquare(); VisibilityGraphGenerator.addPathVertex(destinationPoint); tempAgent.setDestination(destinationPoint); GameObject goalSquare = Instantiate(goalPrefab, destinationPoint.pos, Quaternion.identity); tempAgent.setGoalSquare(goalSquare); // once our agent is spawned and has a destination, we make it walk and we forget about it // the rest of the code logic is delegated to Agent.cs } }
private Vector3 prevPosition; // to know if we're done moving or not // Start is called before the first frame update void Start() { totalFailedAttempts = planningTime = numOfPathsPlanned = totalSucceededAttempts = failedAttempts = 0; // randomly pick a color (two agents CAN have the same colour but this is extremely rare) color = UnityEngine.Random.ColorHSV(); goal.GetComponent <Renderer>().material.color = color; GetComponent <Renderer>().material.color = color; nearbyVertex = getNearbyVertex(); walkToNearbyNeighbor = false; // true when we collided, we randomly walk to nearby neighbor hasPathPlan = false; // canReachGoal = canReachDestination(); setPathPlan(); // we start with a plan }
public void ReUse(PathVertex _prevVertex, Tile _curTile, Tile _endTile) { curTile = _curTile; prevVertex = _prevVertex; if (prevVertex == null) { G = 1; } else { G = prevVertex.G + 1; } H = Mathf.Abs(_endTile.GetX() - curTile.GetX()) + Mathf.Abs(_endTile.GetY() - curTile.GetY()); F = G + H; X = curTile.GetX(); Y = curTile.GetY(); }
public override float MergeMis(CameraPath cameraPath, PathVertex lightVertex, float pdfCameraReverse, float pdfLightReverse, float pdfNextEvent) { int numPdfs = cameraPath.Vertices.Count + lightVertex.Depth; int lastCameraVertexIdx = cameraPath.Vertices.Count - 1; Span <float> camToLight = stackalloc float[numPdfs]; Span <float> lightToCam = stackalloc float[numPdfs]; var pathPdfs = new BidirPathPdfs(lightPaths.PathCache, lightToCam, camToLight); pathPdfs.GatherCameraPdfs(cameraPath, lastCameraVertexIdx); pathPdfs.GatherLightPdfs(lightVertex, lastCameraVertexIdx - 1, numPdfs); // Set the pdf values that are unique to this combination of paths if (lastCameraVertexIdx > 0) // only if this is not the primary hit point { pathPdfs.PdfsLightToCamera[lastCameraVertexIdx - 1] = pdfCameraReverse; } pathPdfs.PdfsLightToCamera[lastCameraVertexIdx] = lightVertex.PdfFromAncestor; pathPdfs.PdfsCameraToLight[lastCameraVertexIdx] = cameraPath.Vertices[^ 1].PdfFromAncestor;
// this method will return the list of vertices that we need to go through // to reach our destination. think of it as an inverted linked list traversal // recall : each pathvertex has a reference to its parent vertex private List <PathVertex> getPath(PathVertex destination) { List <PathVertex> path = new List <PathVertex>(); path.Add(destination); PathVertex current = destination; // the node that will not have a parent is our starting vertex while (current.parentVertex != null) { path.Add(current.parentVertex); current = current.parentVertex; } // because we inversely traversed our 'linked list', we still need to // revert it before we return it path.Reverse(); // void method return(path); }
/// <summary> /// Creates a sample path. /// </summary> /// <returns></returns> private Path CreatePath() { var Points = new PathVertex[9 + 5 + 1]; Points[0] = new PathVertex(10, 10); Points[1] = new PathVertex(50, 10); Points[2] = new PathVertex(10, 50); Points[3] = new PathVertex(50, 55); Points[4] = new PathVertex(25, 75); Points[5] = new PathVertex(125, 125); Points[6] = new PathVertex(250, 250); Points[7] = new PathVertex(200, 35); Points[8] = new PathVertex(250, 10); Points[9] = new PathVertex(300, 50); Points[10] = new PathVertex(350, 10); Points[11] = new PathVertex(450, 200); Points[12] = new PathVertex(301, 200); Points[13] = new PathVertex(350, 350); Points[14] = new PathVertex(250, 350); int[] Indices = new int[45]; Indices[0] = 0; Indices[1] = 1; Indices[2] = 2; Indices[3] = 1; Indices[4] = 2; Indices[5] = 3; Indices[6] = 2; Indices[7] = 3; Indices[8] = 4; Indices[9] = 3; Indices[10] = 4; Indices[11] = 5; Indices[12] = 4; Indices[13] = 5; Indices[14] = 6; Indices[15] = 5; Indices[16] = 6; Indices[17] = 7; Indices[18] = 6; Indices[19] = 7; Indices[20] = 8; Indices[21] = 6; Indices[22] = 8; Indices[23] = 9; Indices[24] = 8; Indices[25] = 9; Indices[26] = 10; Indices[27] = 9; Indices[28] = 10; Indices[29] = 11; Indices[30] = 9; Indices[31] = 12; Indices[32] = 11; Indices[33] = 11; Indices[34] = 12; Indices[35] = 13; Indices[36] = 6; Indices[37] = 14; Indices[38] = 4; Indices[39] = 14; Indices[40] = 6; Indices[41] = 13; Indices[42] = 12; Indices[43] = 6; Indices[44] = 13; var Collection = new Mesh <TriangleVertexData>(Points, Indices); return(new Path(Points, Indices)); }
public override void InitPath(IPathProcessor buffer) { base.InitPath(buffer); this.scene = pathIntegrator.Scene; if (Vertices == null) { Vertices = new PathVertex[scene.MaxPathDepth * 3]; Xvertices = new PathVertex[scene.MaxPathDepth * 3]; } this.pathDensity = 1.0f; this.Radiance = new RgbSpectrum(0f); this.Throughput = new RgbSpectrum(1f); this.PathState = PathTracerPathState.EyeVertex; if (!mutate) { this.Sample = pathIntegrator.Sampler.GetSample(this.Sample); pathIntegrator.Scene.Camera.GetRay(Sample.imageX, Sample.imageY, out this.PathRay); pathStart = PathRay.Org; XRadiance = new RgbSpectrum(); xPathDensity = 1.0f; } else { PathRay.Org = pathStart; PathRay.Dir = -Vertices[0].Wo; this.BackupPath(); this.MutatePath(); mutationCount++; if (mutationCount > MaxMutations) { this.mutate = false; this.mutationCount = 0; this.InitPath(buffer); } } this.RayIndex = -1; this.depth = 0; this.bsdfEvent = BsdfEvent.Specular; this.prevEvent = BsdfEvent.None; shadowRayEvent = BsdfEvent.None; }
/// <summary> /// 어느 경로가 가능한가를 판단 /// </summary> /// <returns>맨 마지막 좌표</returns> PathVertex Simulate() { PathVertex latestVertex = new PathVertex(null, _myCurPos, _destination); while (!latestVertex.myTilePos.Equals(_destination)) { foreach (var direction in DirectionList) { Vector2 nextLocation = latestVertex.myTilePos + direction; if (!Exception(nextLocation)) { PathVertex nextVertex = new PathVertex(latestVertex, nextLocation, _destination); AddinOpenList(nextVertex); } } PathVertex bestVertex = null; if (!_openList.Count.Equals(0)) { bestVertex = _openList[0]; } foreach (var vertex in _openList) { if (bestVertex.Coast >= vertex.Coast) { bestVertex = vertex; } } _openList.Remove(bestVertex); _closeList.Add(bestVertex); latestVertex = bestVertex; if (latestVertex == null) { //길을 찾을수없다 return(null); } } return(latestVertex); }
// public static void addLShape(GameObject LShape){ // LShapeArray[arrayIndex++] = LShape; // MeshFilter[] mfs = LShape.GetComponentsInChildren<MeshFilter>(); // List<Vector3> vList = new List<Vector3>(); // foreach (MeshFilter mf in mfs) { // vList.AddRange (mf.mesh.vertices); // } // } // we retrieve the neighbors of a vertex // note that if we had a large number of vertex or more time for assignment // i would've implemeneted this differently. e.g. vertex class that stores neighbors in a list // so that we don't recalculate every single time // make this return path vertices public static List <PathVertex> getNeighbors(PathVertex vertex) { Physics.SyncTransforms(); bool add; RaycastHit hit; List <PathVertex> neighbors = new List <PathVertex>(); for (int i = 0; i < terrainVertices.Count; i++) { if (Physics.Linecast(vertex.pos, terrainVertices[i].pos, out hit) && hit.transform.tag == "Wall") { continue; // we skip if we hit a wall } add = true; // if collision with spherecast, we can still add if it wasn't with a wall or Lshape Vector3 direction = terrainVertices[i].pos - vertex.pos; float distance = Vector3.Distance(terrainVertices[i].pos, vertex.pos); RaycastHit[] hits = Physics.SphereCastAll(vertex.pos, 3.0f, direction, distance); // do linecast to see if we go over wall as well for (int j = 0; j < hits.Length; j++) { if (hits[j].transform.tag == "LShape") { // Debug.Log(hits[j].transform.tag); add = false; break; // we don't add this vertex } } // finished loop and everything was okay if (add) { neighbors.Add(terrainVertices[i]); } } return(neighbors); }
Path CreateWatchArea() { var Points = new PathVertex[7]; Points[0] = new PathVertex(475, 399); Points[1] = new PathVertex(1108, 353); Points[2] = new PathVertex(871, 251); Points[3] = new PathVertex(821, 218); Points[4] = new PathVertex(752, 232); Points[5] = new PathVertex(752, 216); Points[6] = new PathVertex(1109, 399); var Indices = new int[15]; Indices[0] = 3; Indices[1] = 4; Indices[2] = 5; Indices[3] = 0; Indices[4] = 1; Indices[5] = 6; Indices[6] = 2; Indices[7] = 3; Indices[8] = 4; Indices[9] = 0; Indices[10] = 1; Indices[11] = 4; Indices[12] = 1; Indices[13] = 2; Indices[14] = 4; return(new Path(Points, Indices)); }
/* * void Awake() * { * Owner = GetComponent<Unit>(); * OwnerTrans = Owner.transform; * * _myCurPos = Owner.Position; * Move(new Vector2(49, 19)); * TestPreview(); * bUse = true; * TargetPos = gameObject.transform.position; * } * * * public void TestPreview() * { * for (int i = 0; i < _path.Count; i++) * { * GameObject ret = GameObject.Find("TiledObj_" + (int)_path[i].myTilePos.x + "_" + (int)_path[i].myTilePos.y); * * if (ret != null) * { * MeshRenderer temprend = ret.GetComponent<MeshRenderer>(); * temprend.material.SetColor("_Color", Color.yellow); * } * } * * //if (!_myCurPos.Equals(_destination) && _path.Count > _pathPrograss) * //{ * // _tick = 0f; * // _nextMovePos = _path[_pathPrograss].myTilePos; * // _myCurPos = _nextMovePos; * // _pathPrograss += 1; * //} * } */ /// <param name="destination">목적지 좌표</param> public Vector2 Move(Vector2 destination) { // 초기화 _destination = destination; _path.Clear(); _closeList.Clear(); _openList.Clear(); // 길 구하기 PathVertex latestVertex = Simulate(); PathVertex traceVertex = latestVertex; while (traceVertex != null) { _path.Add(traceVertex); traceVertex = traceVertex.Parent; } _path.Reverse(); // 로그 출력 /* * Debug.Log("Finish"); * for (int i = 0; i < _path.Count; i++) * Debug.Log("Path: " + _path[i].myTilePos.ToString()); */ if (_path.Count >= 2) { return(_path[1].myTilePos); } else { return(_myCurPos); } }
/// <summary> /// Interpolates the position of the given Unit along the Path given the elapsed flight time. /// </summary> /// <param name="elapsedTime">Time that elapsed since the given unit passed by the last PathVertex</param> internal static void InterpolatePosition(Unit unit, int elapsedTime) { LinkedListNode <PathVertex> linkedListNode = unit.LatestTaxiPathNode; unit.taxiTime += elapsedTime; if (linkedListNode.Next == null) { unit.CancelTaxiFlight(); } else { while (linkedListNode.Next.Value.TimeFromStart <= unit.taxiTime) { linkedListNode = linkedListNode.Next; unit.LatestTaxiPathNode = linkedListNode; if (linkedListNode.Next == null) { if (IsNormalSpeed) { unit.m_TaxiMovementTimer.Stop(); return; } ContinueFlight(unit); return; } } PathVertex pathVertex1 = linkedListNode.Value; PathVertex pathVertex2 = linkedListNode.Next.Value; int num = unit.taxiTime - linkedListNode.Value.TimeFromStart; Vector3 newPos = pathVertex1.Pos + (pathVertex2.Pos - pathVertex1.Pos) * num / pathVertex2.TimeFromPrevious; unit.Map.MoveObject(unit, ref newPos); } }
public override float LightTracerMis(PathVertex lightVertex, float pdfCamToPrimary, float pdfReverse, float pdfNextEvent, Vector2 pixel, float distToCam) // pdfNextEvent is either zero, or this is a DI path and we should not ignore the number of shadow rays => base.LightTracerMis(lightVertex, pdfCamToPrimary, pdfReverse, pdfNextEvent * NumShadowRays, pixel, distToCam);
public virtual void MergeUpdate(RgbColor weight, float misWeight, CameraPath cameraPath, PathVertex lightVertex, float pdfCameraReverse, float pdfLightReverse, float pdfNextEvent) { }
protected RgbSpectrum EvaluatePath(PathVertex[] path) { RgbSpectrum Ld = new RgbSpectrum(0f), throughPut = new RgbSpectrum(1f); for (int i = 0; i < path.Length; i++) { if (path[i].Intersection != null) { if (path[i].Bsdf.IsDiffuse()) { var surfaceColor = path[i].Intersection.Material.DiffuseReflectance.Average > path[i].Intersection.Material.GlossReflectance.Average ? path[i].Intersection.Material.DiffuseReflectance : path[i].Intersection.Material.GlossReflectance; var diffRadiance = new RgbSpectrum(); float srd = 0f; for (int j = 0; j < shadowRayCount; j++) { var lightSample = Integrator.UniformSampleLight(ref path[i].Wi, this.manager, this.scene, this.lights, path[i].Intersection, path[i].Bsdf, rnd.Value); if (!lightSample.IsBlack()) { diffRadiance += surfaceColor * lightSample * throughPut; srd += 1f; } } Ld += diffRadiance; /* float lightPdf, lspdf; RayInfo shadowRay; var light = lights[(int) (rnd.Value.NextFloat()*lights.Count)]; lspdf = shadowRayCount/(float) lights.Count; var lightSample = light.Sample(ref path[i].Intersection.Point, ref path[i].Intersection.Normal, rnd.Value.NextFloat(), rnd.Value.NextFloat(), out shadowRay, out lightPdf); if( !lightSample.IsBlack() && !manager.Intersect(shadowRay) ) { var lwi = shadowRay.Dir; var lpt = throughPut*surfaceColor; lightSample *= lpt * Vector.Dot(ref path[i].Intersection.Normal, ref lwi) * path[i].Bsdf.f(ref lwi, ref path[i].Wo, ref path[i].Intersection.ShadingNormal); Ld += lightSample/(lightPdf*lspdf); } */ } if (path[i].BsdfPdf >= MathLab.Epsilon && !path[i].BsdfSample.IsBlack()) { throughPut *= path[i].BsdfSample / path[i].BsdfPdf; } //else { // Ld += throughPut; // break; //} } else if (!path[i].Emittance.IsBlack()) { Ld += throughPut * path[i].Emittance; break; } else { Ld += throughPut * this.SampleEnvironment(ref path[i].Wi); break; } } return Ld / (float)path.Length; }
private void AdvanceNewPath(RayBuffer rayBuffer, SampleBuffer consumer) { int currentTriangleIndex; RayHit rayHit = rayBuffer.rayHits[RayIndex]; Vector wo = -PathRay.Dir; PathVertex vertex = null; if (Vertices[depth] == null) { vertex = new PathVertex(); Vertices[depth] = vertex; } else { vertex = Vertices[depth]; } depth++; bool missed = rayHit.Index == 0xffffffffu; if (missed || PathState == PathTracerPathState.ShadowRaysOnly || depth > scene.MaxPathDepth) { if (missed) { //Radiance += this.scene.SampleEnvironment(ref wo) * Throughput; var sampledEnvironment = this.scene.SampleEnvironment(ref wo); Radiance.MAdd(ref sampledEnvironment, ref Throughput); if (scene.EnvironmentMap != null) { mutate = true; } } Splat(consumer); return; } //var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex); //rayHit.Index += (uint)mesh.StartTriangle; // Something was hit var bsdf = EvalIntersection(ref rayHit); currentTriangleIndex = (int)rayHit.Index; vertex.Bsdf = bsdf; vertex.TriangleIndex = currentTriangleIndex; if (hitInfo == null) { Debugger.Break(); } //If Hit light) if (hitInfo.IsLight) { //if (bsdfEvent.Has(BsdfEvent.Specular) || depth == 1) { var lt = scene.GetLightByIndex(currentTriangleIndex); if (lt != null) { float pdf; var le = hitInfo.Color * lt.Emittance(ref wo, out pdf); //Radiance += Throughput * le; if (!le.IsBlack()) mutate = true; Radiance.MAdd(ref Throughput, ref le); } } Splat(consumer); return; } var hitPoint = PathRay.Point(rayHit.Distance); vertex.HitPoint = hitPoint; tracedShadowRayCount = 0; if (!hitInfo.TextureData.Alpha.IsBlack()) { Throughput *= (RgbSpectrum.UnitSpectrum() - (RgbSpectrum)hitInfo.TextureData.Alpha); PathRay = new RayData(hitPoint, -wo); return; } float fPdf; Vector wi; RgbSpectrum f; hitInfo.TextureData.Throughput = Throughput; prevEvent = bsdfEvent; f = bsdf.Sample_f(ref wo, out wi, ref hitInfo.Normal, ref hitInfo.ShadingNormal, ref Throughput, Sample.GetLazyValue(), Sample.GetLazyValue(), Sample.GetLazyValue() , ref hitInfo.TextureData, out fPdf, out bsdfEvent); //if (prevEvent.Has(BsdfEvent.Transmit) && bsdfEvent.Has(BsdfEvent.Transmit)) //{ // Throughput *= MathLab.Exp(-rayHit.Distance) * 0.2f; //} vertex.BsdfSample = f; vertex.BsdfWeight = fPdf; vertex.Event = bsdfEvent; vertex.Wo = wo; vertex.Wi = wi; vertex.ShadeNormal = hitInfo.ShadingNormal; if ((fPdf <= 0.0f) || f.IsBlack()) { if (tracedShadowRayCount > 0) PathState = PathTracerPathState.ShadowRaysOnly; else { Splat(consumer); } return; } Throughput *= (f * hitInfo.Color) / fPdf; pathDensity *= fPdf; if (depth > scene.MaxPathDepth) { float prob = Math.Max(Throughput.Filter(), scene.RussianRuletteImportanceCap); if (prob >= Sample.GetLazyValue()) { Throughput /= prob; pathDensity *= prob; } else { if (tracedShadowRayCount > 0) PathState = PathTracerPathState.ShadowRaysOnly; else { Splat(consumer); } return; } } PathRay.Org = hitPoint; PathRay.Dir = wi.Normalize(); PathState = PathTracerPathState.NextVertex; }
public void ClearReference() { prevVertex = null; }
public MisDummyPath(float lightArea, int numLightPaths, Vector3[] positions, Vector3[] normals) { this.lightArea = lightArea; this.numLightPaths = numLightPaths; this.positions = positions; this.normals = normals; // Create the light path pathCache = new PathCache(1, 10); var emitterVertex = new PathVertex { Point = new SurfacePoint { Position = positions[0], Normal = normals[0], }, PdfFromAncestor = -10000.0f, PdfReverseAncestor = -10000.0f, // Guard value: this is unused! AncestorId = -1, Depth = 0 }; int emVertexId = pathCache.AddVertex(emitterVertex, 0); // Add all intermediate surface vertices var prevLightVertex = emitterVertex; int prevLightVertexIdx = emVertexId; float lastReverse = 0.0f; float lastNee = 0.0f; for (int idx = 1; idx < normals.Length; ++idx) { // Add the vertex on the first surface var surfaceVertex = new PathVertex { Point = new SurfacePoint { Position = positions[idx], Normal = normals[idx], }, AncestorId = prevLightVertexIdx, Depth = (byte)idx }; // Compute the geometry terms Vector3 dirToLight = prevLightVertex.Point.Position - surfaceVertex.Point.Position; float distSqr = dirToLight.LengthSquared(); dirToLight = Vector3.Normalize(dirToLight); float cosSurfToLight = Vector3.Dot(dirToLight, surfaceVertex.Point.Normal); float cosLightToSurf = Vector3.Dot(-dirToLight, prevLightVertex.Point.Normal); // pdf for diffuse sampling of the emission direction surfaceVertex.PdfFromAncestor = (cosLightToSurf / MathF.PI) * (cosSurfToLight / distSqr); surfaceVertex.PdfReverseAncestor = lastReverse; surfaceVertex.PdfNextEventAncestor = lastNee; lastReverse = (cosSurfToLight / MathF.PI) * (cosLightToSurf / distSqr); if (idx == 1) { surfaceVertex.PdfFromAncestor *= 1.0f / lightArea; // emission surface sampling pdf lastNee = 1.0f / lightArea; // Next event } else { lastNee = 0.0f; } int lightVertexIndex = pathCache.AddVertex(surfaceVertex, 0); prevLightVertex = surfaceVertex; prevLightVertexIdx = lightVertexIndex; } lightEndpointIdx = prevLightVertexIdx; // Create the camera path cameraVertices = new PathPdfPair[positions.Length]; // sampling the camera itself / a point on the lens cameraVertices[0] = new PathPdfPair { PdfFromAncestor = 1.0f, // lens / sensor sampling is deterministic PdfToAncestor = 0.0f }; // primary surface vertex cameraVertices[1] = new PathPdfPair { PdfFromAncestor = numLightPaths * 0.8f, // surface area pdf of sampling this vertex from the camera PdfToAncestor = 1.0f }; // All other surface vertices float nextReverse = lastReverse; int lightVertIdx = lightEndpointIdx; for (int idx = 2; idx < positions.Length; ++idx) { var lightVert = pathCache[0, lightVertIdx]; cameraVertices[idx] = new PathPdfPair { PdfFromAncestor = nextReverse, PdfToAncestor = lightVert.PdfFromAncestor }; nextReverse = lightVert.PdfReverseAncestor; lightVertIdx = lightVert.AncestorId; } // The last camera path vertex is special: it should not already contain the NEE pdf var dir = pathCache[0, 0].Point.Position - pathCache[0, 1].Point.Position; var cossurf = Vector3.Dot(Vector3.Normalize(dir), pathCache[0, 1].Point.Normal); var coslight = Vector3.Dot(Vector3.Normalize(-dir), pathCache[0, 0].Point.Normal); var distsqr = dir.LengthSquared(); cameraVertices[^ 1].PdfFromAncestor = cossurf * coslight / distsqr / MathF.PI;
protected PathVertex[] PropagatePath(RayInfo startRay, int maxPaths) { IntersectionInfo isect; var vertices = new PathVertex[maxPaths]; var ray = new RayInfo(startRay); var sm = rnd.Value; for (int i = 0; i < maxPaths; i++) { Interlocked.Increment(ref stats.totalRays); if (manager.Intersect(ray, out isect)) { var vertice = new PathVertex { Wi = -ray.Dir }; Interlocked.Increment(ref stats.intersections); var triangle = GetTriangle(isect.PrimitiveId, isect.PrimitiveIndex); if (IsLight(triangle)) { var lt = GetLight(triangle.Owner); vertice.Emittance = lt.Le(ray.Dir); vertices[i] = (vertice); break; } vertice.Intersection = isect; var bsdf = matLib.GetSurfMat(isect.Material.Name); vertice.Bsdf = bsdf.First; var t = RgbSpectrum.Unit; vertice.BsdfSample = bsdf.Sample_f(ref vertice.Wi, out vertice.Wo, ref isect.GeometryInfo.GeoNormal, ref isect.GeometryInfo.ShadingNormal, ref t, sm.NextFloat(), sm.NextFloat(), sm.NextFloat(), ref isect.TextureData , out vertice.BsdfPdf, out vertice.SpecularBounce); vertices[i] = (vertice); ray = new RayInfo(isect.GeometryInfo.HitPoint, vertice.Wo); } else { vertices[i] = (new PathVertex() { Wi = -ray.Dir }); break; } } return vertices; }