Bardzo prosty do utworzenia element. Zbudowany z niewielkimi modyfikacjami na kodzie płaszczyzny.
Jeśli chodzi o intersekcję promienia z dyskiem, wyliczamy najpierw intersekcję promienia z płaszczyzną w której leży dysk. Następnie liczymy odległość do środka dysku i porównujemy ją z promieniem dysku.
W stosunku do kodu płaszczyzny modyfikujemy jeszcze kod zwracający współrzędne UVW i UV i gotowe.
Przykładowy kod:
public override Intersection GetIntersection( Intersection a_source_ray_intersection, Ray a_ray) { Vector3 local_start; Vector3 local_dir; TransformToLocal(a_ray, out local_dir, out local_start); if (OneSide) { if (local_dir.Y > 0) return Scene.NoIntersection; } if ((a_source_ray_intersection != null) && (a_source_ray_intersection.SceneObject == this)) { return Scene.NoIntersection; } if (local_dir.Y.AlmostRelativeEquals(0)) return Scene.NoIntersection; double dist = local_start.Y / -local_dir.Y; if (dist <= 0) return Scene.NoIntersection; else { bool back_hit = (local_dir.Y > 0); if (back_hit && OneSide) return Scene.NoIntersection; else { Vector3 local_pos = local_start + local_dir * dist; if (local_pos.X * local_pos.X + local_pos.Z * local_pos.Z > 1) return Scene.NoIntersection; Vector3 world_pos = LocalToWorld * local_pos; dist = (world_pos - a_ray.Start).Length; return new Intersection() { PrevIntersection = a_source_ray_intersection, SceneObject = this, SourceRay = a_ray, Dist = dist, Scene = Scene, BackHit = back_hit, Pos = world_pos, LocalPos = local_pos }; } } } public override Vector3 GetNormal(Intersection a_intersection) { if (a_intersection.BackHit) return -Normal; else return Normal; } public override Vector3 GetUVW(Intersection a_intersection) { return base.GetUVW(a_intersection) * 0.5 + new Vector3(0.5, 0, 0.5); } public override Vector2 GetUV(Intersection a_intersection) { Debug.Assert(a_intersection.UVW.Y.AlmostRelativeEquals(0)); return new Vector2(a_intersection.UVW.X, a_intersection.UVW.Z); } public override void GetTangents(Intersection a_intersection, out Vector3 a_tangent_x, out Vector3 a_tangent_y) { a_tangent_x = Right; a_tangent_y = Forward; } protected override Vector3 LocalScale { get { return new Vector3(Radius, Radius, Radius); } } protected override AABB GetLocalBoundBox() { return new AABB(new Vector3(-Radius, -Constants.MINIMAL_DISTANT, -Radius), new Vector3(Radius, Constants.MINIMAL_DISTANT, Radius)); }
Brak komentarzy:
Prześlij komentarz