// Start is called before the first frame update void Start() { print("Spawned Particle system"); _sourceHandler = sourceLight.GetComponent <IncorporatedParticleImage>(); // _sourceHandler = sourceLight.GetComponent<RefractionBlockFromPointLight>(); // _sourceHandlerTest = sourceLight.GetComponent<VirtualImageProblem>(); }
// Update is called once per frame void Update() { switch (_status) { case Status.SeekingPoints: // Look for points to render to _postComplete = false; // Change how this is done depending on the image type if (imageType == ImageType.OriginalObject || imageType == ImageType.MirrorRealImage) { // Generate corresponding particle system _seekParticleSystem = Instantiate(Resources.Load <GameObject>("Simulations/SphericalSurfaceSeekPS")); if (_seekParticleSystem != null) { // Set transforms to match this object _seekParticleSystem.transform.position = _myPos; _seekParticleSystem.transform.localScale = transform.localScale; // set it's source to this object SeekParticleSystemHandler seekHandler = _seekParticleSystem.AddComponent <SeekParticleSystemHandler>(); seekHandler.myParticleSystem = _seekParticleSystem.GetComponent <ParticleSystem>(); seekHandler.sourceLight = gameObject; if (imageType == ImageType.MirrorRealImage) { seekHandler.sourceImageObject = sourceSceneObject; } } } else if (imageType == ImageType.MirrorVirtualImage) { // SECTION: get border verts Mesh sourceMirrorMesh = sourceSceneObject.GetComponent <MeshFilter>().mesh; Vector3[] verts = sourceMirrorMesh.vertices; // print("Full list of Verts (" + verts.Length + "):\n"); // VertListToString(verts); // SECTION: only unique verts = verts.ToList().Distinct().ToArray(); // print("Only unique verts (" + verts.Length + "):\n"); // VertListToString(verts); // SECTION: convert to world space for (int i = 0; i < verts.Length; i++) { verts[i] = sourceSceneObject.transform.TransformPoint(verts[i]); } // print("Transformed unique verts (" + verts.Length + "):\n"); // VertListToString(verts); // SECTION: Debug with rays // foreach (Vector3 vert in verts) // { // Debug.DrawRay(_myPos, (vert - _myPos).normalized * 15, Color.cyan, Mathf.Infinity); // } // SECTION: create seek mesh verts, set 0 -> myPos Vector3[] newVerts = new Vector3[verts.Length + 1]; newVerts[0] = _myPos; for (int i = 1; i < newVerts.Length; i++) { newVerts[i] = _myPos + (verts[i - 1] - _myPos).normalized * 15; } // print("New mesh verts:"); // VertListToString(newVerts); // SECTION: Debug new verts with lines // foreach (Vector3 vert in newVerts) // { // Debug.DrawLine(_myPos, vert, Color.magenta, Mathf.Infinity); // } // SECTION: assign triangles from newVerts int[] tris = new int[(newVerts.Length - 1) * 3]; for (int i = 0; i < newVerts.Length - 1; i++) { tris[i * 3] = i + 1; if (i + 2 == newVerts.Length) { tris[i * 3 + 1] = 1; } else { tris[i * 3 + 1] = i + 2; } tris[i * 3 + 2] = 0; } // print("Tris list:"); // IntListToString(tris); // SECTION: create gameobject from verts and tris GameObject seekObject = new GameObject(gameObject.name + "VirtualImageSeekCast"); Mesh seekMesh = new Mesh(); seekMesh.vertices = newVerts; seekMesh.triangles = tris; seekMesh.RecalculateNormals(); seekMesh.RecalculateBounds(); // seekObject.AddComponent<MeshRenderer>(); MeshFilter meshFilter = seekObject.AddComponent <MeshFilter>(); meshFilter.mesh = seekMesh; MeshCollider meshCollider = seekObject.AddComponent <MeshCollider>(); meshCollider.convex = true; // meshCollider.sharedMesh = seekMesh; // SECTION: create particle system and check for points _seekParticleSystem = Instantiate(Resources.Load <GameObject>("Simulations/SemiSphericalSurfaceSeekPS")); if (_seekParticleSystem != null) { Vector3 sourceSceneObjectPos = sourceSceneObject.transform.position; Vector3 sourceSceneObjectForward = sourceSceneObject.transform.forward; Vector3 dirToSourceObject = (sourceSceneObjectPos - _myPos).normalized; float dot = Vector3.Dot(dirToSourceObject, sourceSceneObjectForward); dot = dot > 0 ? 1 : -1; _seekParticleSystem.transform.rotation = Quaternion.LookRotation(sourceSceneObjectForward * dot); _seekParticleSystem.transform.position = sourceSceneObjectPos + sourceSceneObjectForward * (dot * 0.05f); Vector3 sourceMirrorTransformLocalScale = sourceSceneObject.transform.localScale; _seekParticleSystem.transform.localScale = new Vector3( sourceMirrorTransformLocalScale.x / 100, sourceMirrorTransformLocalScale.y / 100, sourceMirrorTransformLocalScale.z / 300); SeekParticleSystemHandler particleSystemHandler = _seekParticleSystem.AddComponent <SeekParticleSystemHandler>(); particleSystemHandler.myParticleSystem = _seekParticleSystem.GetComponent <ParticleSystem>(); particleSystemHandler.sourceLight = gameObject; particleSystemHandler.sourceImageObject = sourceSceneObject; particleSystemHandler.validVolume = meshCollider; } } else { print(_myName + ": has unknown imageType: " + imageType); } _status = Status.WaitingForPointSeek; _objectPointsIndex = 0; break; case Status.PreRendering: // collect data and render with appropriate method // Destroy seek particle system (it's done with its work) Destroy(_seekParticleSystem); // Complete this object's job is it is done if (_objectPointsIndex.Equals(_objectPointsToRender.Count)) { print(_myName + ": completed all points to render! Status is now COMPLETE"); _status = Status.Complete; break; } // Get the appropriate data for the current object indexed _curTargetObject = _objectsInScene[_objectPointsIndex]; _curInteractionPoint = _objectPointsToRender[_objectPointsIndex]; print(_myName + ": Rendering point: " + _curInteractionPoint); // Check the type of object, and render if (_curTargetObject.GetComponent <PlaneMirrorDef>() != null) { print(_myName + ": point " + _curInteractionPoint + " is a plane mirror! Rendering..."); _status = Status.PlaneMirrorRendering; } else if (_curTargetObject.GetComponent <SphericalMirrorDef>() != null) { print(_myName + ": point " + _curInteractionPoint + " is a spherical mirror! Rendering..."); _status = Status.SphericalMirrorRendering; } else if (_curTargetObject.GetComponent <ThinLensDef>() != null) { print(_myName + ": point " + _curInteractionPoint + " is a thin lens! Rendering..."); _status = Status.ThinLensRendering; } else // WTF? { print(_myName + ": Encountered unknown object: " + _curTargetObject.name); _curTargetObject.GetComponent <Renderer>().material.color = Color.red; } break; case Status.PlaneMirrorRendering: ObjectSeekHits curSeekHit = _objectSeekHits[_objectPointsIndex]; print(_myName + ": rendering a plane mirror from " + _myPos + " to " + _curInteractionPoint + " on mirror " + curSeekHit.ObjName); Vector3 mirrorNorm = curSeekHit.HitNormal; Vector3 exitDir = Quaternion.AngleAxis(180, mirrorNorm) * -(_curInteractionPoint - _myPos).normalized; float imageDistance = Vector3.Distance(_myPos, _curInteractionPoint); Debug.DrawLine(_myPos, _curInteractionPoint, Color.cyan, Mathf.Infinity); Debug.DrawRay(_curInteractionPoint, mirrorNorm, Color.red, Mathf.Infinity); Debug.DrawRay(_curInteractionPoint, exitDir, Color.green, Mathf.Infinity); Debug.DrawRay(_curInteractionPoint, -exitDir * imageDistance, Color.yellow, Mathf.Infinity); Vector3 outputImagePos = _curInteractionPoint - exitDir * imageDistance; print(_myName + ": Found image location at " + outputImagePos); GameObject image = Instantiate(Resources.Load <GameObject>("Objects/ParticleImagePoint"), outputImagePos, Quaternion.identity); // Give this new virtual image a unique name to be identified by image.name = _myName + " (Virtual image) " + _generatedImageId; _generatedImageId++; IncorporatedParticleImage incorporatedParticleImage = image.GetComponent <IncorporatedParticleImage>(); incorporatedParticleImage.imageType = ImageType.MirrorVirtualImage; incorporatedParticleImage.sourceSceneObject = _curTargetObject; print(_myName + ": created virtual image of " + _curTargetObject.name + " with name " + image.name); // Return to prerendering for the next point _objectPointsIndex++; _status = Status.PreRendering; print(_myName + ": moving to work on point index " + _objectPointsIndex + ". going back to prerendering"); break; case Status.SphericalMirrorRendering: curSeekHit = _objectSeekHits[_objectPointsIndex]; print(_myName + ": rendering a spherical mirror from " + _myPos + " to " + curSeekHit.ObjName); // Get target spherical mirror def SphericalMirrorDef sphericalMirrorDef = _curTargetObject.GetComponent <SphericalMirrorDef>(); // Get direction to mirror origin Vector3 rayToOrigin = (sphericalMirrorDef.GetPos() - _myPos).normalized; // Get direction to mirror center of curvature Vector3 rayToCenterOfCurvature = (sphericalMirrorDef.GetCenter() - _myPos).normalized; //// Calculate reflection vector // Get which side object is on Vector3 targetForward = _curTargetObject.transform.forward; float objectDot = Vector3.Dot(targetForward, rayToOrigin); int clampDot = objectDot > 0 ? 1 : -1; // Calculate exit dir Vector3 hitNormal = targetForward * clampDot; exitDir = Quaternion.AngleAxis(180, hitNormal) * -rayToOrigin; // Calculate intersection point between if (Math3d.ClosestPointsOnTwoLines(out Vector3 cp1, out Vector3 cp2, sphericalMirrorDef.GetPos(), exitDir.normalized, _myPos, rayToCenterOfCurvature)) { float distanceBetween = Vector3.Distance(cp1, cp2); if (distanceBetween < 0.1f) { Vector3 avgPoint = (cp1 + cp2) / 2; print(_myName + ": Found spherical image loc at " + avgPoint); // Generate new image from point image = Instantiate(Resources.Load <GameObject>("Objects/ParticleImagePoint"), avgPoint, Quaternion.identity); // Give this new virtual image a unique name to be identified by image.name = _myName + " (Virtual image) " + _generatedImageId; _generatedImageId++; incorporatedParticleImage = image.GetComponent <IncorporatedParticleImage>(); // Detect if it is a virtual or real image float imagePointDot = Vector3.Dot(targetForward, (sphericalMirrorDef.GetCenter() - avgPoint).normalized); incorporatedParticleImage.imageType = imagePointDot > 0 ? ImageType.MirrorRealImage : ImageType.MirrorVirtualImage; incorporatedParticleImage.sourceSceneObject = _curTargetObject; print(_myName + ": created virtual image of " + _curTargetObject.name + " with name " + image.name); // Return to prerendering for the next point _objectPointsIndex++; _status = Status.PreRendering; print(_myName + ": moving to work on point index " + _objectPointsIndex + ". going back to prerendering"); } else { print(_myName + ": Points are not close! Distance: " + distanceBetween); } } else { print(_myName + "Handle image straight on"); } break;