public override Color shade(RenderContext rc, Ray ray, HitRecord hrec, int depth) { Point hp = ray.pointOn(hrec.getT()); Vector normal = hrec.getPrimitive().normal(hp); hp += 0.0001f * normal; Scene scene = rc.getScene(); int numlights = scene.numberOfLights(); Color finalc = new Color(0,0,0); for ( int i = 0; i < numlights; i++ ) { Vector ldir = new Vector(); Color lcolor = new Color(); float ldist = scene.getLight(i).getLight(ref lcolor, ref ldir, rc, hp); HitRecord shadowhr = new HitRecord(); Ray shadowray = new Ray(hp, ldir); scene.getObject().intersect(ref shadowhr, rc, shadowray); if ( shadowhr.getT() >= ldist || shadowhr.getT() < 0.01 ) { float dp = Vector.dot(normal, ldir); if( dp > 0 ) { finalc += dp*lcolor; } } } return color * ( finalc * kd + scene.getAmbient() * ka ); }
public Color renderPixel(int x, int y) { Color color; HitRecord hitRecord = new HitRecord(); Ray ray; RenderContext renderContext = new RenderContext( this.scene ); float step = 2 / (float)this.scene.getXResolution(); float xStart = -1 + ( 0.5f * step ); float yStart = (-(float)this.scene.getYResolution() * (0.5f * step)) + (0.5f * step); ray = this.scene.getCamera().generateRay( xStart + (x * step), yStart + (y * step) ); this.scene.traceRay( ray, hitRecord, renderContext ); if ( hitRecord.getT() == float.PositiveInfinity || hitRecord.getMaterial() == null || hitRecord.getPrimitive() == null ) { color = this.scene.getBackground().getColor( renderContext, ray ); } else { color = hitRecord.getMaterial().shade( renderContext, ray, hitRecord, 1 ); } return color; }
public override void intersect(ref HitRecord hit, RenderContext rc, Ray ray) { float num = Vector.dot( -this.norm, ray.p() - this.point ); float denom = Vector.dot( this.norm, ray.d() ); float t = num/denom; if ( denom==0 || num==0 || t < 0 ) hit.hit( float.PositiveInfinity, this, this.material ); else hit.hit( num/denom, this, this.material ); }
public override void intersect(ref HitRecord hit, RenderContext rc, Ray ray) { Vector dist = ray.p() - this.p; float b = Vector.dot(dist, ray.d()); float c = Vector.dot(dist, dist) - this.r2(); float d = b * b - c; float t = (d > 0) ? -b - (float)System.Math.Sqrt(d) : float.PositiveInfinity; hit.hit(t, this, this.material); }
public override bool Scatter(Ray rayIn, HitRecord rec, out Vector3 attenuation, out Ray scattererd, ImSoRandom random) { Vector3 reflected = Vector3.Reflect(rayIn.Direction, rec.Normal); attenuation = new Vector3(1.0f); Vector3 outward_normal; float niOverNt; float cosine; if (Vector3.Dot(rayIn.Direction, rec.Normal) > 0) { outward_normal = -rec.Normal; niOverNt = _refIndex; cosine = _refIndex * Vector3.Dot(rayIn.Direction, rec.Normal) / rayIn.Direction.Length(); } else { outward_normal = rec.Normal; niOverNt = 1.0f / _refIndex; cosine = -Vector3.Dot(rayIn.Direction, rec.Normal) / rayIn.Direction.Length(); } Vector3 refracted; float reflectProb; if (Refract(rayIn.Direction, outward_normal, niOverNt, out refracted)) { reflectProb = Schlick(cosine, _refIndex); } else { reflectProb = 1.0f; } if (random.NextFloat() < reflectProb) { scattererd = new Ray(rec.P, reflected, rayIn.Time); } else { scattererd = new Ray(rec.P, refracted, rayIn.Time); } return(true); }
public override bool Scatter(Ray r_in, HitRecord rec, out Vec3 attenuation, out Ray scattered) { Vec3 reflected = Vec3.Reflect(r_in.Direction, rec.Normal); attenuation = Vec3.Create(1.0); Vec3 outward_normal; double ni_over_nt; double consine; if (r_in.Direction.Dot(rec.Normal) > 0) { outward_normal = -rec.Normal; ni_over_nt = _ref_idx; consine = _ref_idx * r_in.Direction.Dot(rec.Normal) / r_in.Direction.Length; } else { outward_normal = rec.Normal; ni_over_nt = 1 / _ref_idx; consine = -r_in.Direction.Dot(rec.Normal) / r_in.Direction.Length; } Vec3 refracted; double reflect_probe; if (Vec3.Refract(r_in.Direction, outward_normal, ni_over_nt, out refracted)) { reflect_probe = Function.Schlick(consine, _ref_idx); } else { reflect_probe = 1.0; } if (_sampler.NextDouble() < reflect_probe) { scattered = new Ray(rec.P, reflected, r_in.Time); } else { scattered = new Ray(rec.P, refracted, r_in.Time); } return(true); }
private void HitSphere(SphereRecord sphere, Ray ray, float tMin, float tMax, out HitRecord hitRecord) { Vector3 oc = ray.origin - sphere.Center; float a = Vector3.Dot(ray.direction, ray.direction); float b = Vector3.Dot(oc, ray.direction); float c = Vector3.Dot(oc, oc) - sphere.Radius * sphere.Radius; float discriminant = b * b - a * c; if (discriminant < 0.0f) { hitRecord = null; return; } float temp = (-b - Mathf.Sqrt(discriminant)) / a; if (temp < tMax && temp > tMin) { Vector3 point = ray.GetPoint(temp); hitRecord = new HitRecord() { T = temp, Point = point, Normal = (point - sphere.Center) / sphere.Radius, Material = sphere.Material, }; return; } temp = (-b + Mathf.Sqrt(discriminant)) / a; if (temp < tMax && temp > tMin) { Vector3 point = ray.GetPoint(temp); hitRecord = new HitRecord() { T = temp, Point = point, Normal = (point - sphere.Center) / sphere.Radius, Material = sphere.Material, }; return; } hitRecord = null; }
public bool Hit(Ray r, double tMin, double tMax, out HitRecord hitRec) { var oc = r.Origin - Center; var a = r.Dir.LengthSquared; var halfB = Vec3.Dot(oc, r.Dir); var c = oc.LengthSquared - Radius * Radius; var disc = halfB * halfB - a * c; if (disc < 0) { hitRec = default(HitRecord); return(false); } var sqrtd = Math.Sqrt(disc); var root = (-halfB - sqrtd) / a; if (root < tMin || tMax < root) { root = (-halfB + sqrtd) / a; if (root < tMin || tMax < root) { hitRec = default; return(false); } } var t = root; var point = r.At(t); var outwardNormal = (point - Center) / Radius; GetSphereUV(outwardNormal, out var u, out var v); hitRec = new HitRecord { T = t, Point = point, Material = Material, U = u, V = v }; hitRec.SetFaceNormal(r, outwardNormal); return(true); }
public override bool scatter(Ray in_ray, ref HitRecord hr, out Color attenuation, out Ray scattered) { Vector3 outward_normal; Vector3 reflected = Vector3.Reflect(in_ray.direction, hr.raycastHit.normal); float in_over_nt; attenuation = new Color(1f, 1f, 1f); Vector3 refracted; float reflect_prob; float cosine; if (Vector3.Dot(in_ray.direction, hr.raycastHit.normal) > 0) { outward_normal = -hr.raycastHit.normal; in_over_nt = ref_idx; cosine = ref_idx * Vector3.Dot(in_ray.direction, hr.raycastHit.normal) / in_ray.direction.magnitude; } else { outward_normal = hr.raycastHit.normal; in_over_nt = 1f / ref_idx; cosine = -Vector3.Dot(in_ray.direction, hr.raycastHit.normal) / in_ray.direction.magnitude; } if (Common.refract(in_ray.direction, outward_normal, in_over_nt, out refracted)) { //scattered = new Ray(hr.raycastHit.point, refracted); reflect_prob = Common.schlick(cosine, ref_idx); } else { reflect_prob = 1.0f; } if (Common.random.NextDouble() < reflect_prob) { scattered = new Ray(hr.raycastHit.point, reflected); } else { scattered = new Ray(hr.raycastHit.point, refracted); } return(true); }
public new HitRecord Intersect(Ray ray) { //Transform ray to object coordinate system Ray transfRay = RayTransformer.TransformRayToObject(ray, InvTransformationMatrix); HitRecord hit = Intersectable.Intersect(transfRay); if (hit != null) { if (Material != null) { hit.Material = Material; } //Transform HitRecrod back to world coordinate system RayTransformer.TransformHitToWorld(hit, TransformationMatrix, TransposedTransformationMatrix); } return(hit); }
public bool Hit(Ray r, double t_min, double t_max, out HitRecord rec) { rec = null; HitRecord temp_rec; bool hit_anything = false; double closest_so_far = t_max; foreach (var hitable in _list) { if (hitable.Hit(r, t_min, closest_so_far, out temp_rec)) { hit_anything = true; closest_so_far = temp_rec.T; rec = temp_rec; } } return(hit_anything); }
public bool Hit(Ray ray, double tMin, double tMax, out HitRecord hit) { hit = default; var hitAnything = false; var closestSoFar = tMax; foreach (var @object in _objects) { if (@object.Hit(ray, tMin, closestSoFar, out hit)) { hitAnything = true; closestSoFar = hit.T; } } return(hitAnything); }
public Color Integrate(Ray ray, IIntersectable objects, List <ILight> lights, ISampler sampler, List <List <Sample> > subPathSamples, LightSample lightSample) { Color returnColor = new Color(0, 0, 0); /* * Core Ray Tracing algorithm */ HitRecord record = objects.Intersect(ray); if (record != null && record.Distance > 0 && record.Distance < float.PositiveInfinity) { foreach (ILight light in lights) { returnColor.Append(record.Material.Shade(record, light.GetLightDirection(record.IntersectionPoint)).Mult(light.GetIncidentColor(record.IntersectionPoint))); } } return(returnColor); }
public virtual bool Hit(Ray r, double tMin, double tMax, out HitRecord rec) { rec = new HitRecord(); HitRecord tempRec = new HitRecord(); bool hitAnything = false; double closestSoFar = tMax; //没有物体遮挡的情况下我们可以看无限远 for (int i = 0; i < list.Count; i++) { if (list[i].Hit(r, tMin, closestSoFar, out tempRec)) { hitAnything = true; closestSoFar = tempRec.t; //当有物体遮挡视线之后视线可达到的最远处就是上一个击中点 rec = tempRec; } } return(hitAnything); }
private void HitColliders(Ray ray, float tMin, float tMax, out HitRecord hitRecord) { RaycastHit hitInfo; ray.origin += ray.direction * tMin; if (!Physics.Raycast(ray, out hitInfo, tMax - tMin)) { hitRecord = null; return; } hitRecord = new HitRecord() { Material = FindMaterial(hitInfo.transform), Normal = hitInfo.normal, Point = hitInfo.point, }; }
public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord hit) { HitRecord tempRecord = new HitRecord(); bool hitted = false; float closest = t_max; for (int i = 0; i < this.hitLists.Count; i++) { if (this.hitLists[i].Hit(ray, t_min, closest, ref tempRecord)) { hit = tempRecord; closest = tempRecord.t; hitted = true; } } return(hitted); }
public override bool Scatter(Ray rIn, HitRecord rec, out Vec3 attenuation, out Ray scattered) { Vec3 outwardNormal = new Vec3(); Vec3 reflected = Vec3.Reflect(rIn.Direction(), rec.Normal); double niOverNt; attenuation = new Vec3(1.0, 1.0, 1.0); Vec3 refracted = new Vec3(); double reflectProb; double cosine; if (Vec3.Dot(rIn.Direction(), rec.Normal) > 0) { outwardNormal = -rec.Normal; niOverNt = _refIndex; cosine = _refIndex * Vec3.Dot(rIn.Direction(), rec.Normal) / rIn.Direction().Length(); } else { outwardNormal = rec.Normal; niOverNt = 1.0 / _refIndex; cosine = -Vec3.Dot(rIn.Direction(), rec.Normal) / rIn.Direction().Length(); } if (Vec3.Refract(rIn.Direction(), outwardNormal, niOverNt, out refracted)) { reflectProb = Schlick(cosine, _refIndex); } else { reflectProb = 1.0; } if (FastRandom.RandomDouble() < reflectProb) { scattered = new Ray(rec.P, reflected, rIn.Time()); } else { scattered = new Ray(rec.P, refracted, rIn.Time()); } return(true); }
/// <summary> /// Event handler for the timeline control.MouseDownPicked event</summary> /// <param name="sender">Timeline control that we are attached to</param> /// <param name="e">Event args</param> protected virtual void Owner_MouseDownPicked(object sender, HitEventArgs e) { HitRecord hitRecord = e.HitRecord; TimelinePath hitObject = hitRecord.HitPath; if (hitObject != null) { Keys modifiers = Control.ModifierKeys; if (e.MouseEvent.Button == MouseButtons.Left) { if (modifiers == Keys.None && SelectionContext != null && SelectionContext.SelectionContains(hitObject)) { // The hit object is already selected. Wait until the mouse up to see if there was // a drag or not. If no drag, then set the selection set to be this one object. m_mouseDownHitRecord = hitRecord; m_mouseDownPos = e.MouseEvent.Location; } else if (modifiers == Keys.Control) { // Either this object is not already selected or Shift key is being held down. // to be consistent with the Windows interface. m_mouseDownHitRecord = hitRecord; m_mouseDownPos = e.MouseEvent.Location; } else if ((modifiers & Keys.Alt) == 0) { // The 'Alt' key might mean something different. If no Alt key, we can update the // selection immediately. UpdateSelection(hitRecord, modifiers); } } else if (e.MouseEvent.Button == MouseButtons.Right) { if (modifiers == Keys.None && SelectionContext != null && !SelectionContext.SelectionContains(hitObject)) { // The hit object is not already selected and a right-click landed on it. Select it. UpdateSelection(hitRecord, modifiers); } } } }
public bool Scatter(Ray ray, HitRecord record, ref Vector attenuation, ref Ray scattered) { attenuation = albedo.GetColor(record.U, record.V, record.P); var refracted = Vector.Zero; Vector outwardNormal; float newRefractivity; float cosin; float possible; var reflected = Reflect(ray.Direction, record.Normal); if (ray.Direction.Dot(record.Normal) > 0f) { outwardNormal = record.Normal.Negative(); newRefractivity = refractivity; cosin = ray.Direction.Normalize().Dot(record.Normal); } else { outwardNormal = record.Normal; newRefractivity = 1f / refractivity; cosin = -ray.Direction.Normalize().Dot(record.Normal); } if (Refract(ray.Direction, outwardNormal, newRefractivity, ref refracted)) { possible = SchlickEquation(cosin, newRefractivity); } else { scattered = new Ray(record.P, reflected); possible = 1f; } // reflection or refraction if (MathHelper.Randf() < possible) { scattered = new Ray(record.P, reflected); } else { scattered = new Ray(record.P, refracted); } return(true); }
public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord rec) { void GetSphereUV(ref HitRecord record) { float phi = Mathf.Atan2(record.p.z, record.p.x); float theta = Mathf.Asin(record.p.y); record.u = 1 - (phi + Mathf.PI) / (2 * Mathf.PI); record.v = (theta + Mathf.PI / 2) / Mathf.PI; } var oc = ray.origin - center; var a = Vector3.Dot(ray.direction, ray.direction); var b = 2f * Vector3.Dot(oc, ray.direction); var c = Vector3.Dot(oc, oc) - radius * radius; var discriminant = b * b - 4 * a * c; if (!(discriminant > 0)) { return(false); } var temp = (-b - Mathf.Sqrt(discriminant)) / a * 0.5f; if (temp < t_max && temp > t_min) { rec.shader = shader; rec.t = temp; rec.p = ray.GetPoint(rec.t); rec.normal = (rec.p - center).Normalized(); GetSphereUV(ref rec); return(true); } temp = (-b + Mathf.Sqrt(discriminant)) / a * 0.5f; if (!(temp < t_max) || !(temp > t_min)) { return(false); } rec.shader = shader; rec.t = temp; rec.p = ray.GetPoint(rec.t); rec.normal = (rec.p - center).Normalized(); GetSphereUV(ref rec); return(true); }
public override void Kill(NTGBattleUnitController killer) { if (alive) { base.Kill(killer); unitAnimator.SetBool("dead", true); HitRecord lastPlayerHit = null; while (hitRecords.Count > 0) { var hitRecord = hitRecords.Dequeue() as HitRecord; var p = hitRecord.shooter as NTGBattlePlayerController; if (p != null) { lastPlayerHit = hitRecord; } } if (lastPlayerHit != null && Time.time - lastPlayerHit.time < mainController.configX) { var k = lastPlayerHit.shooter as NTGBattlePlayerController; k.statistic.towerKill++; } GetComponent <CapsuleCollider>().enabled = false; gun.gameObject.SetActive(false); if (warningHint != null) { warningHint.gameObject.SetActive(false); warningDeadHint.gameObject.SetActive(false); } foreach (var fx in transform.GetComponentsInChildren <ParticleSystem>()) { fx.Stop(); } PlayDeadFX(); mainController.uiController.ShowUnitKillMessage(killer, this); StartCoroutine(doDead()); } }
private Color32 Diffusing(Ray ray, HitableList hitableList, int depth) { var record = new HitRecord(); if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { var r = new Ray(Vector3.zero, Vector3.zero); var attenuation = Color32.black; if (depth >= MAX_SCATTER_TIME || !record.material.scatter(ray, record, ref attenuation, ref r)) { return(Color32.black); } var c = Diffusing(r, hitableList, depth + 1); return(new Color32(c.r * attenuation.r, c.g * attenuation.g, c.b * attenuation.b)); } var t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color32(1, 1, 1) + t * new Color32(0.5f, 0.7f, 1)); }
void CookerTree_DragDrop(object sender, DragEventArgs e) { Node data = e.Data.GetData(typeof(Node)) as Node; if (data == null) { return; } Point p = this.PointToClient(new Point(e.X, e.Y)); HitRecord hit = Pick(p); if (hit.Node != null) { Node dest = hit.Node; if (!(dest.Tag is CookTask)) { return; } dest.Expanded = true; ICookBase cb = Activator.CreateInstance((Type)data.Tag) as ICookBase; Node newNode = dest.Add(cb); newNode.Label = cb.GetName(); cb.PropertyChanged += (src, args) => { newNode.Label = cb.GetName(); }; { ((CookTask)hit.Node.Tag).Targets.Add((CookTarget)cb); newNode.IsLeaf = true; } } else { ICookBase cb = Activator.CreateInstance((Type)data.Tag) as ICookBase; Node newNode = Root.Add(cb); newNode.Label = cb.GetName(); cb.PropertyChanged += (src, args) => { newNode.Label = cb.GetName(); }; document.CookingItems.Add(cb); } }
public override bool Scatter(RTRay ray, HitRecord hit, out Color attenuation, out RTRay scattered) { attenuation = new Color(1, 1, 1); Vector3 outwardN; float ni_over_nt; Vector3 refracted; float reflect_prob; float cosine; if (Vector3.Dot(ray.direction, hit.n) > 0) { outwardN = -hit.n; ni_over_nt = refractiveIndex; cosine = Vector3.Dot(ray.direction, hit.n) / ray.direction.magnitude; } else { outwardN = hit.n; ni_over_nt = 1.0f / refractiveIndex; cosine = -Vector3.Dot(ray.direction, hit.n) / ray.direction.magnitude; } if (RTMath.Refract(ray.direction, outwardN, ni_over_nt, out refracted)) { reflect_prob = RTMath.schlick(cosine, refractiveIndex); } else { reflect_prob = 1.0f; } if (RTMath.Rnd01() < reflect_prob) { scattered = new RTRay().Set(hit.p, RTMath.Reflect(ray.direction, hit.n)); } else { scattered = new RTRay().Set(hit.p, refracted); } return(true); }
private static HitRecord GetWorldHit(Ray r, dWorldBuffer world, float minT) { HitRecord rec = GetSphereHit(r, world.spheres, minT); HitRecord vRec = world.VoxelChunk.hit(r, minT, rec.t); HitRecord triRec = GetMeshHit(r, world, vRec.t); if (rec.t < vRec.t && rec.t < triRec.t) { return(rec); } else if (vRec.t < rec.t && vRec.t < triRec.t) { return(vRec); } else { return(triRec); } }
public bool Hit(Ray r, float tMin, float tMax, out HitRecord rec) { rec = HitRecord.Empty; bool hitAnything = false; float closestSoFar = tMax; for (int i = 0; i < Spheres.Length; i++) { Sphere elem = Spheres[i]; if (elem.Hit(r, tMin, closestSoFar, out HitRecord tempRec)) { hitAnything = true; closestSoFar = tempRec.T; rec = tempRec; } } return(hitAnything); }
public bool Scatter(Ray rIn, HitRecord hitRecord, out Vector3 attenuation, out Ray scattered) { Vector3 outwardNormal; var reflected = HelperFunctions.Reflect(rIn.Direction(), hitRecord.Normal); float niOverNt; attenuation = new Vector3(1.0f, 1.0f, 1.0f); float cosine; if (Vector3.Dot(rIn.Direction(), hitRecord.Normal) > 0) { outwardNormal = -hitRecord.Normal; niOverNt = RefIdx; cosine = RefIdx * Vector3.Dot(rIn.Direction(), hitRecord.Normal) / rIn.Direction().Length(); } else { outwardNormal = hitRecord.Normal; niOverNt = 1.0f / RefIdx; cosine = -Vector3.Dot(rIn.Direction(), hitRecord.Normal) / rIn.Direction().Length(); } float reflectProb; if (HelperFunctions.Refract(rIn.Direction(), outwardNormal, niOverNt, out Vector3 refracted)) { reflectProb = HelperFunctions.Schlick(cosine, RefIdx); } else { reflectProb = 1.0f; } var random = new Random(); if (random.NextDouble() < reflectProb) { scattered = new Ray(hitRecord.P, reflected); } else { scattered = new Ray(hitRecord.P, refracted); } return(true); }
/// <summary> /// Checks if the ray intersects with the sphere at a certain point /// </summary> /// <param name="ray"></param> /// <param name="minDist"></param> /// <param name="maxDist"></param> /// <param name="hitRecord"></param> /// <returns></returns> public bool Hit(Ray ray, double minDist, double maxDist, out HitRecord hitRecord) { hitRecord = new HitRecord(); hitRecord.Material = this.Material; Vector3 oc = ray.Origin - (Vector3)this.Origin; // Ray Origin - Center of the Sphere = OC double a = ray.Direction.LengthSquared; double half_b = Vector3.Dot(oc, ray.Direction); double c = oc.LengthSquared - Radius * Radius; double discriminant = half_b * half_b - a * c; if (discriminant > 0) { double root = Math.Sqrt(discriminant); double temp = (-half_b - root) / a; if (temp < maxDist && temp > minDist) { hitRecord.Distance = temp; hitRecord.Point = ray.PointAtDistance(hitRecord.Distance); Vector3 outwardNormal = ((Vector3)hitRecord.Point - this.Origin) / this.Radius; // determine if ray faces normal hitRecord.HitFront = Vector3.Dot(ray.Direction, outwardNormal) < 0; hitRecord.Normal = hitRecord.HitFront ? outwardNormal : -outwardNormal; return(true); } temp = (-half_b + root) / a; if (temp < maxDist && temp > minDist) { hitRecord.Distance = temp; hitRecord.Point = ray.PointAtDistance(hitRecord.Distance); Vector3 outwardNormal = ((Vector3)hitRecord.Point - this.Origin) / this.Radius; // determine if ray faces normal hitRecord.HitFront = Vector3.Dot(ray.Direction, outwardNormal) < 0; hitRecord.Normal = hitRecord.HitFront ? outwardNormal : -outwardNormal; return(true); } } return(false); }
/// <summary> /// Updates the selection set, given the hit object and the modifier keys</summary> /// <param name="hitRecord">HitRecord</param> /// <param name="modifiers">Modifier keys</param> private void UpdateSelection(HitRecord hitRecord, Keys modifiers) { TimelinePath hitObject = hitRecord.HitPath; bool hitIsValidAnchor = true; switch (hitRecord.Type) { case HitType.GroupMove: SelectGroups(hitObject); break; case HitType.TrackMove: SelectTracks(hitObject); break; case HitType.Interval: case HitType.Key: case HitType.Marker: SelectEvents(hitObject); Owner.Constrain = (modifiers & Owner.ConstrainModifierKeys) != 0; break; default: Anchor = null; hitIsValidAnchor = false; break; } if (hitIsValidAnchor) { // If the Shift key is not held down or the current Anchor is null, or the user // has switched between track and group, or the user has picked an event, then // update the Anchor. IEvents are always additive with the shift key. if ((modifiers & Keys.Shift) == 0 || Anchor == null || (Anchor.Last is IGroup && hitObject.Last is ITrack) || (Anchor.Last is ITrack && hitObject.Last is IGroup) || (Anchor.Last is IEvent && hitObject.Last is IEvent)) { Anchor = hitObject; } } }
public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord rec) { HitRecord rec1 = new HitRecord(), rec2 = new HitRecord(); if (boundary.Hit(ray, -float.MaxValue, float.MaxValue, ref rec1)) { if (boundary.Hit(ray, rec1.t + 0.0001f, float.MaxValue, ref rec2)) { rec1.t = Mathf.Range(rec1.t, t_min, t_max); if (rec1.t < t_min) { rec1.t = t_min; } if (rec2.t > t_max) { rec2.t = t_max; } if (rec1.t >= rec2.t) { return(false); } if (rec1.t < 0) { rec1.t = 0; } float distance_inside_boundary = (rec2.t - rec1.t) * ray.direction.length(); float hit_distance = -(1 / density) * Mathf.Log(Mathematics.Random.Get()); if (hit_distance < distance_inside_boundary) { rec.t = rec1.t + hit_distance / ray.direction.length(); rec.p = ray.GetPoint(rec.t); rec.normal = new Vector3(1, 0, 0); // arbitrary rec.shader = phase_function; return(true); } } } return(false); }
public override bool scatter(Ray rin, HitRecord rec, ref Vec3 attenuation, ref Ray scattered) { Vec3 outwardNormal; Vec3 reflected = reflect(rin.direction(), rec.normal); float niOverNt; attenuation = new Vec3(1.0F, 1.0F, 1.0F); Vec3 refracted = new Vec3(); float reflectProb; float cosine; if (Vec3.dot(rin.direction(), rec.normal) > 0) { outwardNormal = -rec.normal; niOverNt = refIdx; cosine = refIdx * Vec3.dot(rin.direction(), rec.normal) / rin.direction().Length(); } else { outwardNormal = rec.normal; niOverNt = 1 / refIdx; cosine = -Vec3.dot(rin.direction(), rec.normal) / rin.direction().Length(); } if (refract(rin.direction(), outwardNormal, niOverNt, ref refracted)) { reflectProb = schlick(cosine, refIdx); } else { scattered = new Ray(rec.p, reflected); reflectProb = 1.0F; } if (new Random().NextDouble() < reflectProb) { scattered = new Ray(rec.p, reflected); } else { scattered = new Ray(rec.p, refracted); } return(true); }
void TestBoxesIntersectionBasic() { Box box = new Box(); Ray ray1 = new Ray(new Point(-5f, 0f, 0f), Constant.VEC_X); HitRecord? intersection1 = box.rayIntersection(ray1); Assert.True(intersection1 != null, "TestBoxesIntersectionBasic failed - assert 1/10"); // new Vec2D(0.375f, 0.8333334f) for other method UV mapping HitRecord hit1 = new HitRecord( new Point(-1.0f, 0.0f, 0.0f), new Normal(-1.0f, 0.0f, 0.0f), new Vec2D(0.125f, 0.5f), 4.0f, ray1 ); Assert.True(hit1.isClose(intersection1), "TestBoxesIntersectionBasic failed - assert 2/10"); Assert.True(box.quickRayIntersection(ray1), "TestBoxesIntersectionBasic failed - assert 3/10"); Ray ray2 = new Ray(new Point(0f, 0f, 10f), -Constant.VEC_Z); HitRecord? intersection2 = box.rayIntersection(ray2); Assert.True(intersection2 != null, "TestBoxesIntersectionBasic failed - assert 4/10"); // new Vec2D(0.625f, 0.5f) for other method UV mapping HitRecord hit2 = new HitRecord( new Point(0.0f, 0.0f, 1.0f), new Normal(0.0f, 0.0f, 1.0f), new Vec2D(0.875f, 0.5f), 9.0f, ray2 ); Assert.True(hit2.isClose(intersection2), "TestBoxesIntersectionBasic failed - assert 5/10"); Assert.True(box.quickRayIntersection(ray2), "TestBoxesIntersectionBasic failed - assert 6/10"); Ray ray3 = new Ray(new Point(-5f, 0f, 10f), Constant.VEC_X); HitRecord? intersection3 = box.rayIntersection(ray3); Assert.True(intersection3 == null, "TestBoxesIntersectionBasic failed - assert 7/10"); Assert.False(box.quickRayIntersection(ray3), "TestBoxesIntersectionBasic failed - assert 8/10"); // Intersect for t<0 Ray ray4 = new Ray(new Point(0f, 3f, 0f), Constant.VEC_Y); HitRecord? intersection4 = box.rayIntersection(ray4); Assert.True(intersection4 == null, "TestBoxesIntersectionBasic failed - assert 9/10"); Assert.False(box.quickRayIntersection(ray4), "TestBoxesIntersectionBasic failed - assert 10/10"); }
// TODO: Merge with BunnyCrownState public override void HandleCollision(GameObject player, Collider2D collision, ref Vector3 velocity) { Bunny bunny = collision.GetComponent <Bunny>(); Player enemy = collision.GetComponent <Player>(); Vector3 knockbackForce = velocity; if (bunny) { HitRecord hitRecord = new HitRecord(); bunny.Hit(player, ref hitRecord, knockbackForce); } else if (enemy) { // Trying to hit the enemy player HitRecord hitRecord = new HitRecord(); enemy.Hit(player, ref hitRecord, knockbackForce); // If an enemy is hit, the dash stops Player self = player.GetComponent <Player>(); if (self.collisionInfo.below) { self.controller.SwitchState(PlayerController.States.IDLE); } else { self.controller.SwitchState(PlayerController.States.AIRBORNE); } // If the dash was reflected because of a collision with a dashing player, both players are repelled in the opposite facing direction if (hitRecord.reflected) { Player hitPlayer = hitRecord.hitObject as Player; Vector2 reflectDirection = hitPlayer.transform.position - player.transform.position; reflectDirection.Normalize(); velocity = reflectDirection * 10.0f; Debug.Log("Reflected!"); } } }
public override bool Hit(Ray r, double tMin, double tMax, out HitRecord rec) { Vec3 oc = r.Origin() - Center(r.Time()); double a = Vec3.Dot(r.Direction(), r.Direction()); double b = Vec3.Dot(oc, r.Direction()); double c = Vec3.Dot(oc, oc) - _radius * _radius; double discriminant = b * b - a * c; if (discriminant > 0) { double temp = (-b - Math.Sqrt(b * b - a * c)) / a; if (temp < tMax && temp > tMin) { rec.T = temp; rec.P = r.PointAtParameter(rec.T); rec.Normal = (rec.P - Center(r.Time())) / _radius; rec.Material = _material; Sphere.GetSphereUV((rec.P - Center(r.Time())) / _radius, out rec.U, out rec.V); return(true); } temp = (-b + Math.Sqrt(b * b - a * c)) / a; if (temp < tMax && temp > tMin) { rec.T = temp; rec.P = r.PointAtParameter(rec.T); rec.Normal = (rec.P - Center(r.Time())) / _radius; rec.Material = _material; Sphere.GetSphereUV((rec.P - Center(r.Time())) / _radius, out rec.U, out rec.V); return(true); } } rec.T = 0.0; rec.P = null; rec.Normal = null; rec.Material = null; rec.U = 0.0; rec.V = 0.0; return(false); }
/// <summary> /// Intersects the specified client point with the scene, knowing that the given /// HitRecords were the result of having called Dispatch with these same client points</summary> /// <param name="x">Client x coordinate</param> /// <param name="y">Client y coordinate</param> /// <param name="hits">The hits</param> /// <param name="pt">The intersection point</param> /// <param name="surfaceNormal">The surface normal of the target object at the intersection /// point, or the zero vector if the surface normal could not be found. Check against /// Vec3F.ZeroVector before using.</param> /// <returns>True iff client point intersects scene</returns> protected bool Intersect(int x, int y, HitRecord[] hits, ref Vec3F pt, out Vec3F surfaceNormal) { surfaceNormal = new Vec3F(); if (hits.Length == 0) return false; HitRecord hit = hits[0]; if (hit.HasNormal) surfaceNormal = hit.Normal; if (hit.HasWorldIntersection) { pt = hit.WorldIntersection; return true; } return false; }
/// <summary> /// Dispatches untyped items. Replaces DispatchNotTyped(). To get the same behavior as /// the old DispatchNotTyped(), set the TypeFilter property to null prior to calling.</summary> /// <param name="traverseList">The traverse list</param> /// <param name="camera">The camera</param> protected void DispatchTraverseList(ICollection<TraverseNode> traverseList, Camera camera) { // Prepare for geometric picking -- create the ray in world space and reset geometric hit-list. // First create the ray in viewing coordinates and transform to world coordinates. float nx = (m_x / (float)m_width) - 0.5f;//normalized x float ny = 0.5f - (m_y / (float)m_height);//normalized y Ray3F rayWorld = camera.CreateRay(nx, ny); Matrix4F worldToView = camera.ViewMatrix; Matrix4F viewToWorld = new Matrix4F(); viewToWorld.Invert(worldToView); rayWorld.Transform(viewToWorld); ClearHitList(); // for geometric picking. will be cleared for each HitRecord. List<uint> userData = new List<uint>(1); // Dispatch traverse list int index = 0; foreach (TraverseNode node in traverseList) { // First test for filtering. IRenderObject renderObject = node.RenderObject; if (FilterByType(renderObject)) { IIntersectable intersectable = renderObject.GetIntersectable(); IGeometricPick geometricPick = intersectable as IGeometricPick; if (geometricPick != null) { // Picking by geometry. Matrix4F objToWorld = new Matrix4F(node.Transform); Matrix4F worldToObj = new Matrix4F(); worldToObj.Invert(objToWorld); Matrix4F viewToObj = Matrix4F.Multiply(viewToWorld, worldToObj); if (m_frustumPick) { //The pick frustum is in view space. Transform to world space then object space. Frustum frustumObj = new Frustum(m_viewFrust0); frustumObj.Transform(viewToObj); //Multi-pick. Get everything in the pick frustum (m_viewFrust0). Vec3F eyeObj; worldToObj.Transform(camera.Eye, out eyeObj); userData.Clear(); if (geometricPick.IntersectFrustum(frustumObj, eyeObj, node.RenderState, userData)) { // Prepare a multi-pick HitRecord, as if OpenGL had calculated this. HitRecord hit = new HitRecord( node.GraphPath, renderObject, objToWorld, userData.ToArray()); m_geoHitList.Add(hit); } } else { //Single pick. We care about distance from camera eye. //Make a copy of the ray in world-space and tranform it to object space. Ray3F rayObj = rayWorld; //remember, Ray3F is a value type, not a reference type. rayObj.Transform(worldToObj); // Do the intersection test in object space. userData.Clear(); Vec3F intersectionPt, surfaceNormal; Vec3F nearestVert; bool intersected; intersected = geometricPick.IntersectRay( rayObj, camera, node.RenderState, objToWorld, this, out intersectionPt, out nearestVert, out surfaceNormal, userData); if (intersected) { // Transform to world space and then to screen space. objToWorld.Transform(intersectionPt, out intersectionPt); objToWorld.Transform(nearestVert, out nearestVert); // Prepare a single-pick HitRecord, as if OpenGL had calculated this. HitRecord hit = new HitRecord( node.GraphPath, renderObject, objToWorld, userData.ToArray()); // This is the one difference from OpenGL pick. We have the world pt already. hit.WorldIntersection = intersectionPt; hit.NearestVert = nearestVert; // Another difference is that it's possible to get the surface normal. if (surfaceNormal != Vec3F.ZeroVector) { objToWorld.TransformNormal(surfaceNormal, out surfaceNormal); surfaceNormal.Normalize(); hit.Normal = surfaceNormal; } m_geoHitList.Add(hit); } } } else { // Picking by "rendering", using OpenGL pick. PushMatrix(node.Transform, false); Gl.glPushName(index); IRenderPick pickInterface = renderObject as IRenderPick; if (pickInterface != null) { pickInterface.PickDispatch(node.GraphPath, node.RenderState, this, camera); } else { renderObject.Dispatch(node.GraphPath, node.RenderState, this, camera); } Gl.glPopName(); PopMatrix(); } } index++; } }
/// <summary> /// Shoots a ray into the scene and returns the intersection point</summary> /// <param name="camera">The camera</param> /// <param name="x">Ray X coordinate in screen space</param> /// <param name="y">Ray y coordinate in screen space</param> /// <param name="scene">The given scene</param> /// <param name="point">The point of intersection</param> /// <param name="firstHit">The HitRecord giving possible nearest vertex and surface normal</param> /// <returns>True if the ray intersects the scene</returns> public bool Intersect(Camera camera, int x, int y, Scene scene, ref Vec3F point, out HitRecord firstHit) { firstHit = null; //Too small of a pick tolerance makes Design View tooltips and right-click context //menus not work on wireframe / linework. //m_pickTolerance = 0.001f; Init(camera, x, y, x, y, false, true); Dispatch(scene, camera); HitRecord[] hits = GetHits(); //m_pickTolerance = 3.0f; if (hits.Length == 0) return false; firstHit = hits[0]; if (firstHit.HasWorldIntersection) { point = firstHit.WorldIntersection; return true; } return false; }
/// <summary> /// Gets the HitRecord array from a given traverse list</summary> /// <param name="traverseList">The traverse list</param> /// <param name="multiPick">True to return all available HitRecords. False to return just the closest</param> /// <returns>HitRecord array</returns> /// <remarks>Must be called after Init() and Dispatch(). There can potentially be duplicate /// HitRecords returned for two reasons: 1) Proxy objects, like the cube by default, render /// themselves twice, once with solid fill and once with the outline. Both renderings can /// yield a HitRecord, sometimes with slightly different z values. 2) Models are made up of /// multiple TransformNodes and each one can generate a HitRecord.</remarks> public HitRecord[] GetHits(ICollection<TraverseNode> traverseList, bool multiPick) { if (m_frustumPick == true && multiPick == false) throw new InvalidOperationException("results can't be sorted front-to-back with frustum picking"); // First get the hits from OpenGL pick. Gl.glRenderMode resets this value when it is called, // so consecutive calls to GetHits() will fail. Thus, we need to cache glRenderMode(GL_RENDER). if (m_openGlHits == 0) { m_openGlHits = Gl.glRenderMode(Gl.GL_RENDER); } HitRecord[] renderSelect = null; if (m_openGlHits > 0 && traverseList.Count > 0) { renderSelect = PopulateOpenGlSelection(traverseList); } else { renderSelect = s_emptyHitRecordArray; } // now integrate the hits from geometrical picking. HitRecord[] select; if (m_geoHitList.Count == 0) { select = renderSelect; } else { int total = renderSelect.Length + m_geoHitList.Count; select = new HitRecord[total]; renderSelect.CopyTo(select, 0); m_geoHitList.CopyTo(select, renderSelect.Length); } // sort the results by distance from camera eye, near-to-far if (m_frustumPick == false) HitRecord.Sort(select, m_eye); // if the caller only wants one result, just give them one. if (multiPick == false && select.Length > 1) { HitRecord[] singleHit = new HitRecord[1]; singleHit[0] = select[0]; select = singleHit; } // useful debug output //Console.WriteLine("multiPick:{0}, m_frustumPick:{1}", multiPick, m_frustumPick); //foreach (HitRecord hit in select) //{ // Console.WriteLine(" hit: {0} at z {1}", hit.RenderObject.InternalObject.Id, hit.ZMin); //} // return the results return select; }
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { throw new NotImplementedException(); }
private void SetManipulator(IManipulator manipulator, HitRecord[] hits) { s_isManipulating = true; m_manipulatorHitRecords = hits; }
public abstract void intersect(ref HitRecord hit, RenderContext rc, Ray ray);
/// <summary> /// Performs actions at the beginning of control drag</summary> /// <param name="hit">Hit record</param> /// <param name="x">Mouse x position</param> /// <param name="y">Mouse y position</param> /// <param name="action">Render action</param> /// <param name="camera">Camera</param> /// <param name="transform">Transform</param> /// <returns>Code for control element under mouse x, y</returns> public HitElement OnHit(HitRecord hit, float x, float y, IRenderAction action, Camera camera, Matrix4F transform) { // Store pick coords m_iX = x; m_iY = y; return (HitElement)hit.RenderObjectData[1]; }
public void traceRay(Ray ray, HitRecord hr, RenderContext rc) { this.obj.intersect(ref hr, rc, ray); }
public override Color shade(RenderContext rc, Ray ray, HitRecord hrec, int depth) { Scene scene = rc.getScene(); Point hp = ray.pointOn(hrec.getT()); Vector normal = hrec.getPrimitive().normal(hp); Vector v = scene.getCamera().getEye() - hp; v.normalize(); hp += 0.0001f * normal; int numlights = scene.numberOfLights(); Color finalc = new Color(0,0,0); for(int i = 0; i < numlights; i++) { Vector ldir = new Vector(); Color lcolor = new Color(); float ldist = scene.getLight(i).getLight(ref lcolor, ref ldir, rc, hp); HitRecord shadowhr = new HitRecord(); Ray shadowray = new Ray(hp, ldir); scene.getObject().intersect(ref shadowhr, rc, shadowray); if((shadowhr.getT() >= ldist || shadowhr.getT() < 0.01)) { float dp = Vector.dot(normal, ldir) * this.kd; if(!(dp > 0)) dp = 0; Vector r = 2*(Vector.dot(ldir, normal))*normal - ldir; r.normalize(); float spec = Vector.dot(r, v); if(!(spec > 0)) spec = 0; else spec = (float)System.Math.Pow(spec, this.n); finalc += (dp*kd+spec*ks)*lcolor; } } return color*(finalc + scene.getAmbient()*ka); }
public abstract Color shade( RenderContext rc, Ray ray, HitRecord hrec, int depth );
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { bool isHit = false; foreach (SceneObject obj in components) { bool currentHit = obj.IsHit(ray, record, float.MinValue, float.MaxValue); isHit = isHit || currentHit; } if (RenderingParameters.showMouse && isHit) { Console.WriteLine("Hit by " + record.ObjectName); Console.WriteLine("t: " + record.T); Console.WriteLine("Distance: " + record.Distance); } return isHit; }
/// <summary> /// Comparer for sorting HitRecords by their HitType enum. Lower-valued enums come first.</summary> private int CompareHits(HitRecord x, HitRecord y) { return x.Type.CompareTo(y.Type); }
private HitRecord[] PopulateOpenGlSelection(ICollection<TraverseNode> traverseList) { // Ensure that OpenGL is in correct state. double[] viewMat = null; double[] projectionMat = null; int[] viewport = null; if (m_frustumPick == false) { Gl.glViewport(0, 0, m_width, m_height); Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_projectionMatrix); Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Util3D.glMultMatrixf(m_viewMatrix); viewMat = new double[16]; Gl.glGetDoublev(Gl.GL_MODELVIEW_MATRIX, viewMat); projectionMat = new double[16]; Gl.glGetDoublev(Gl.GL_PROJECTION_MATRIX, projectionMat); viewport = new int[4]; viewport[0] = viewport[1] = 0; viewport[2] = m_width; viewport[3] = m_height; } // Construct traverse array HitRecord[] selection = null; List<HitRecord> selectionList = new List<HitRecord>(); TraverseNode[] travArray = new TraverseNode[traverseList.Count]; traverseList.CopyTo(travArray, 0); uint start = 0; for (int i = 0; i < m_openGlHits; ++i) { uint nameCount = (uint)m_selectionBuffer[start]; if (nameCount > 0) { uint travNodeIndex = (uint)m_selectionBuffer[start + 3]; TraverseNode travNode = travArray[travNodeIndex]; HitRecord hitRecord; if (m_frustumPick) { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); } else { hitRecord = new HitRecord( travNode.GraphPath, travNode.RenderObject, new Matrix4F(travNode.Transform), new uint[nameCount - 1]); // Transform screen to world and record world-space intersection point. float zMin = ((float)((uint)m_selectionBuffer[start + 1])) / 0xFFFFFFFF; Vec3F intersectionPt = GetWorldIntersectionFromScreen( m_x, m_y, zMin, viewMat, projectionMat, viewport); hitRecord.WorldIntersection = intersectionPt; } // Populate object data for (uint j = 0; j < nameCount - 1; j++) { hitRecord.RenderObjectData[j] = (uint)m_selectionBuffer[start + 4 + j]; } selectionList.Add(hitRecord); start += 3 + nameCount; } } selection = new HitRecord[selectionList.Count]; selectionList.CopyTo(selection, 0); return selection; }
/// <summary> /// Performs a picking test to see if any manipulator is visible on the screen at the given coordinates</summary> /// <param name="x">X-coordinate in screen coordinates (like from MouseEventArgs)</param> /// <param name="y">Y-coordinate in screen coordinates (like from MouseEventArgs)</param> /// <param name="hits">Resulting HitRecord(s) if there was a manipulator found</param> /// <returns>The found manipulator or null if none found</returns> protected IManipulator TestForManipulator(int x, int y, out HitRecord[] hits) { IManipulator manipulator = null; m_pickAction.TypeFilter = typeof(IManipulator); SetCurrentContext(); m_pickAction.Set(m_renderAction); m_pickAction.Init(Camera, x, y, x, y, true, false); Render(m_pickAction, true, true); hits = m_pickAction.GetHits(); m_pickAction.TypeFilter = null; // Analyze hits if (hits.Length > 0) manipulator = hits[0].RenderObject as IManipulator; m_pickAction.Clear(); return manipulator; }
/// <summary> /// Constructor</summary> /// <param name="hits">HitRecords for event</param> /// <param name="multiSelect">Whether user selecting multiple objects</param> public PickEventArgs(HitRecord[] hits, bool multiSelect) { HitArray = hits; MultiSelect = multiSelect; }
public override void intersect(ref HitRecord hit, RenderContext rc, Ray ray) { for( int i = 0; i < this.objects.Count; i++ ) this.objects[i].intersect( ref hit, rc, ray ); }
/// <summary> /// Performs actions during control drag</summary> /// <param name="hit">Hit record</param> /// <param name="x">Mouse x position</param> /// <param name="y">Mouse y position</param> /// <param name="action">Render action</param> /// <param name="camera">Camera</param> /// <param name="transform">Transform</param> /// <returns>Translation, in world coordinates</returns> public Vec3F OnDrag(HitRecord hit, float x, float y, IRenderAction action, Camera camera, Matrix4F transform) { float a1, a2; Matrix4F W = new Matrix4F(); W.Mul(transform, camera.ViewMatrix); // Setup rays, in view space. (-z goes into the screen.) Ray3F ray0 = camera.CreateRay(m_iX, m_iY); Ray3F ray = camera.CreateRay(x, y); // Build axis and origin in view space Vec3F xAxis = W.XAxis; Vec3F yAxis = W.YAxis; Vec3F zAxis = W.ZAxis; Vec3F origin = W.Translation; Vec3F trans = new Vec3F(); // Choose the best projection plane according to the projection angle switch ((HitElement)hit.RenderObjectData[1]) { case HitElement.X_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(xAxis, p1 - p0); Vec3F xLocal = transform.XAxis; trans = dragAmount * xLocal; } break; case HitElement.Y_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(yAxis, p1 - p0); Vec3F yLocal = transform.YAxis; trans = dragAmount * yLocal; } break; case HitElement.Z_ARROW: { a1 = Math.Abs(Vec3F.Dot(ray0.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(ray0.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = ray0.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = ray.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot(zAxis, p1 - p0); Vec3F zLocal = transform.ZAxis; trans = dragAmount * zLocal; } break; case HitElement.XY_SQUARE: { Vec3F p0 = ray0.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F p1 = ray.IntersectPlane(zAxis, -Vec3F.Dot(zAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragY = Vec3F.Dot(yAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F yLocal = transform.YAxis; trans = dragX * xLocal + dragY * yLocal; } break; case HitElement.YZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F p1 = ray.IntersectPlane(xAxis, -Vec3F.Dot(xAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragY = Vec3F.Dot(yAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F yLocal = transform.YAxis; Vec3F zLocal = transform.ZAxis; trans = dragY * yLocal + dragZ * zLocal; } break; case HitElement.XZ_SQUARE: { Vec3F p0 = ray0.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F p1 = ray.IntersectPlane(yAxis, -Vec3F.Dot(yAxis, origin)); Vec3F deltaLocal = p1 - p0; float dragX = Vec3F.Dot(xAxis, deltaLocal); float dragZ = Vec3F.Dot(zAxis, deltaLocal); Vec3F xLocal = transform.XAxis; Vec3F zLocal = transform.ZAxis; trans = dragX * xLocal + dragZ * zLocal; } break; } return trans; }
private HitRecord Pick(Point pt) { HitRecord result = new HitRecord(); int left = -m_hScroll; int xPadding = Margin.Left; foreach (Property p in Properties) { if (p.FirstInCategory) { if (pt.Y < HeaderHeight && pt.X >= left && pt.X <= left + ExpanderSize + 2 * xPadding) { result.Type = HitType.CategoryExpander; result.Property = p; result.Category = p.Category; result.Row = -1; result.Offset = new Point(pt.X - left, pt.Y); return result; } if (!GetVisible(p)) left += RowHeight; } if (GetVisible(p)) { int width = GetColumnInfo(p).Width; if (pt.X >= left && pt.X <= left + width) { result.Property = p; if ((pt.Y >= 0) && (pt.Y < HeaderHeight)) { if (Math.Abs(left + width - pt.X) < SystemDragSize.Width) { result.Type = HitType.ColumnHeaderRightEdge; result.Offset = new Point(pt.X - left, pt.Y); return result; } else { result.Type = HitType.ColumnHeader; result.Offset = new Point(pt.X - left, pt.Y); return result; } } // check if after the property editing row int row = GetRowAtY(pt.Y); if (row < SelectedObjects.Length) { result.Offset = new Point(pt.X - left, pt.Y % RowHeight); result.Type = HitType.Cell; result.Row = row; } return result; } left += width; } } return result; }
/// <summary> /// Returns whether the control was hit during a picking operation</summary> /// <param name="hit">Hit record</param> /// <returns>True if the control was hit during a picking operation</returns> public bool IsHit(HitRecord hit) { return (hit.RenderObjectData[0] == m_nameBase); }