A short Shapes Tutorial for Raja |
Here is a quick tutorial on shapes in Raja. Actually, this page
is for developers. A simple user won't find anything interesting in
it. So it must be written somewhere:
The shapes are 3D objects that we want to draw by
ray-tracing.
Shape3D (I) | +--Solid (I) | +--Form (I) | +--TexturedForm (I)
As you see on the "magnificent" ascii art figure, the Shape3D is an interface (I) which all the 3D Object implement. It contains only three methods:
Well, the first problem is to define a simple geometrical form,
as a sphere, a plane or anything else. So let's jump to
Form.
Form (I) | +--BasicForm (A) | +--Plane | +--Sphere | +...
A Form is an interface which represent a geometric form, but we assume that it will contain information only about the general geometry of the shape. It is implemented only by BasicForm for the moment but we can imagine to add more complex Forms like gaseous, fractal, or random Forms. Form extends Shape3D with the following intersect method:
A LocaGeometry, as we will see further is a way to handle the local geometry of the intersection. We hide in it the normal and the coordinates of the intersection.
Let's see BasicForm now !
So a BasicForm is just a simple geometric form as sphere, plane, cone, cylinder, torus, ... Actually we can define plenty of them ! We just have to know the equation of it and how to solve the intersection with a ray. It implements the intersect method for the geometric form we are considering.
Ok, what's next ? Well we have to consider the texture
of the shape. So, let now jump to
TexturedForm.
TexturedForm (I) | +--BasicTexturedForm | +--Complement | +--CompositeForm (A) | +--Intersection | +--Union
TexturedForm is an Interface too. It's just a Shape3D with a Texture linked to it. It extends Shape3D with the following intersect method:
So the only difference with Form is that the intersect method returns a TexturedLocalGeometry instead of a (non textured) LocaGeometry.
We have several flavor of
TexturedForms. We
can have a basic one
(BasicTexturedForm)
which is composed of a single form. We can have the complement of a
textured form
(Complement). And,
finally, we can put several textured forms together either in a
Union, either in an
Ok, now what is exactly a TexturedLocalGeometry ?
Let's see.
Point3D | +--LocalGeometry (A) | +--TexturedLocalGeometry (A) | +--SolidLocalGeometry
Doh, I feel you're in need of some more details about this,
aren't you ?
Ok, everything is coming from Point3D. Basically a Point3D is just three coordinates (x,y,z). The methods are:
Hey, I said we have to define it later, remember ? :-)
Point3D | +--LocalGeometry (A)
LocaGeometry is an abstract class to handle a point with a normal (or it can be seen as a tangent plane at this point) attached to it. With this structure you can use only the informations that you need without requiring the whole shape when you get the intersection. In a sense you handle only the local geometry of the intersection (this explains the name).
LocaGeometry has an extra abstract method:
Point3D | +--LocalGeometry (A) | +--TexturedLocalGeometry (A)
The class TexturedLocalGeometry adds two extra abstract methods to get the texture of the shape:
LocalTexture is just a structure defining the local material properties of the form. It contains the local:
Here comes the SolidLocalGeometry !
Point3D | +--LocalGeometry (A) | +--TexturedLocalGeometry (A) | +--SolidLocalGeometry
This class introduces the notion of refraction. Actually we didn't need this before reaching this point. The extra methods are:
To understand the goal of the methods inVolumeUndefined and outVolumeUndefined, consider the intersection of a Ray with a Sphere, but with the ray travelling inside the Sphere. At the intersection point, the inner refractive index is the refractive index of the Sphere (since the Ray is "leaving" the Sphere at the intersection). However, the outer refractive index is not known by the Sphere, and hence the Sphere will assign it to undefined.
If this Sphere is part of an Aggregate, then the Aggregate will check whether this intersection is inside another solid of the Aggregate, and if this is the case it will assign the outer refractive index (at the intersection) to the refractive index of that container Solid. Finally, when the intersection is returned from the main Aggregate of the Scene, we check whether the outer (resp. inner) Volume is undefined, and in that case we use the ambiant refractive index instead.
But, now what about the
Volume ?
Volume have been introduced to handle the concept of transparent objects. We tried to be as abstract as possible to allows to define object with a refractive index that can continuously vary on the volume. I don't know if it is possible to compute the trajectory of a light ray on those object but that could be funny ! :-)
So, basically a Volume give the refractive index of a 3D object. It has only one method which is:
But how the Volume and the Shape3D are related ?
Let's do some ascii art again ! :-)
Shape3D (I) Volume (I) | | | +--IsotropicVolume | | +---------+----------+ | +--Solid (I) | +--BasicSolid | +--Aggregate
Hey, not bad ! Is there some ascii art contest ? I really believe I can compete ! ;-)
So, as the nice figure show it, the class Solid is an implementation of both Shape3D and Volume. Actually, all the Raja scenes use Solid everywhere. Because it is defined by a (set of) TexturedForm(s) and by a (set of) Volume(s).
Ok, but we want to be able to build some more complex solids than
simply a shape. We want to manage
Aggregate. That's why
we defined the class
BasicSolid which is
only one Solid (aka one
TexturedForm and
one Volume) and the
class Aggregate. But
Aggregate is
slightly more complex, let talk about it.
Actually, an Aggregate is just a list of BasicSolids with a DirectedGraph.
Ok, you probably can figure that the list of BasicSolid is just all the Solid which are in this Aggregate. But what the Hell is this DirectedGraph ?
Remember that we have to deal with transparency ! So when several objects are transparent in an Aggregate and that their intersection is not empty, then we have a problem !
On the intersection what refractive index must we take in account ?
How clever we are !
We just defined a DirectedGraph that can say the priority of each transparent object on the others !
Well, but there is still something puzzling me ! Did we forget some details ?
Let's see, we have the textured forms, the refractive index, the intersection, union or complement, the priority of the transparent Volumes on the others...
Yes, of course ! I forgot to define what a Texture
is !
Ok, let be more specific about the textures now. There is one class Texture:
Texture (I) | +--PlainTexture
It contains one method which is:
Actually when you call a method getInLocalTexture or
getOutLocalTexture you call the method getLocalTexture on the
Texture (in or out)
linked to the shape. The
Texture contains the
way to fill all the fields of a
LocalTexture
according to the Point3D we
are considering (see the description of
LocalTexture
above).
Well, now I think we have completed this tour of Raja Objects ! Ok, let see now the complete class hierarchy of shapes.
Get ready,...
START !
Shape3D (I) Volume (I) | | | +--IsotropicVolume | | +---------+----------+ | | | +--Solid (I) | | | +--BasicSolid | | | +--Aggregate | +--Form (I) | | | +--BasicForm (A) | | | +--Plane | | | +--Sphere | | | +... | +--TexturedForm (I) | +--BasicTexturedForm | +--Complement | +--CompositeForm (A) | +--Intersection | +--Union
I must get an award on ascii art for this ! Don't you
think ? :o)