3d Interface Mechanics
Choosing a Language:
I chose to use C# for my 3d interface because the language
works very conveniently with the DirectX API. Initialization is simple and the code
produced is very clean. I decided that performance didn’t matter on behalf of
the base program, but rather in the vertex / pixel shaders. The only
calculations in the base program are simple vector and matrix mathematics.
Therefore, I decided that C++ wasn’t needed and it would create more of a
burden than a performance advantage.
The base 3d Control:
The base class of my 3d interface library is the Control3D
class. This class contains properties, methods, and events that all controls in
my library have in common.
Here are a few key properties:
- Width,
height, top, left – These describe the size and location of the control.
- DXDevice
– This is a pointer to the DirectX device that will eventually draw the
control. This is needed by every control so that it can load textures,
meshes, get DirectX properties, and to actually draw the control.
- Shader
– This is a very vital property to all controls. This is the effect file
that contains the pixel and vertex shader to use for the control. This is
what gives each control its distinct visual look and effect.
Here are a few key methods:
- Each
changeable property has accessors and mutators implemented by C#’s “get”
and “set” functions.
- SetDevice
(virtual) – This is an internal method that is called by the Form3D class
(since the device used by the Form3D object is the same as the controls).
This method sets the DXDevice object for use later in the program. It also
loads media needed by all controls and is virtual so that other control
classes can load specifically what they want in addition to what every
control needs.
- DrawControl
(virtual) – Every control is obviously going to be drawn at one point or
another. This method is called when the Form3D class needs to draw the
control. It draws everything common to all controls and is virtual so
other controls can draw specifically what they need.
The Form3D Control:
Just as a 2D application needs a form to contain all of its
controls, so does a 3D application. The Form3D control is the container for
every control added to the application. It handles things such as mouse
movements and clicks. These calculations are quite involved because the class
is essentially taking mouse movements and clicks in a 2D plane and transforming
them to 3D space. The calculations make use of vectors, rays, and 3D geometry
to see if the mouse is over or has been clicked on a 3D control.
Other classes used by
my 3D interface:
To give the interface a heightened sense of interactivity
and 3D space, I decided to incorporate dynamic shading changes through pixel
shaders and 3D movement including rotation. In order to implement these things,
I created classes to make these processes easier. Two of these classes are the
TimeCycle class and the VectorMorph class.
- The TimeCycle class is used to implement
time into the controls’ movements. For example, many functions need a
consistent time cycle to control the speed of movement. The TimeCycle
class works by providing a function that returns a value between 0 and X,
where X is the maximum value in seconds. The value is calculated based on
the difference between the current system time, and the system time when
the program was opened. If the difference is larger than X, it is divided modularly
by X so the value returned is never outside the range of 0 and X.
- The VectorMorph class takes a list of
vectors and starts a morph cycle. The class uses the TimeCycle class to
morph to the next vector over a certain period of time. It does this by multiplying
each component of the current vector by a percent (based on the time
cycle) and adding it to the next vector which is multiplied by 100 – the percent
mentioned above. The result from this addition will be a combination of both
the current vector and the next vector based on the amount of time that
has passed since the current vector was fully displayed.