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