3D Templates |
Top Previous Next |
This section shows more complex programs and code fragments that illustrate the process of writing programs and using the more advanced features of the 3D intrinsics.
I. Simplest Possible Program. This example illustrates the simplest possible 3D program by displaying a tetrahedron. It expands the example given in the Step-by-step section and shows how a full program is written. The full source for the program is in the Tetra3D example program.
A. Declare A Mesh Handle. This step declarers an integer variable to hold the handle for a 3D mesh.
int WrkMesh;
B. Set Up Viewer Window. This code sets the 3D window size and position, sets the window background color and enables the window:
Set3DWindow(200,10,430,380); Set3DBackColor($002F2F1F); Enable3DViewer(true);
C. Create A 3D Mesh Object. This code gets a handle for a 3D mesh and stores it in the variable WrkMesh.
WrkMesh:= Add3DObject(-1, 1,"WrkMesh");
D. Build Tetrahedron. This code adds four triangles to the mesh, one for each face of the tetrahedron, each one a different color:
Add3DTriangle(WrkMesh,-1.0,-1.0,-1.0, -1.0, 1.0, 1.0, 1.0, 1.0,-1.0, $FF0000FF); Add3DTriangle(WrkMesh,-1.0,-1.0,-1.0, 1.0, 1.0,-1.0, 1.0,-1.0, 1.0, $FF00FF00); Add3DTriangle(WrkMesh,-1.0,-1.0,-1.0, 1.0,-1.0, 1.0, -1.0, 1.0, 1.0, $FFFF0000); Add3DTriangle(WrkMesh,-1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 1.0,-1.0, $FF0000FF);
E. Scale Object. This code fits the tetrahedron to the window so the user can see the full object:
FitTo3DWindow(-2,0);
F. Enable Mouse Control. This code configures the viewer so the user can manipulate the object with the mouse:
Mouse3DControl(true,false,false);
G. Wait. This line of code waits for the user to hit any key before terminating the program. Without this line of code the program would simply terminate before the user could do anything. The mouse manipulation feature works even while EXPL is waiting for keyboard input.
C:= Chin(1);
II. Draw Cube From Array. This code fragment illustrates displaying a more complex object by loading the data from a constant array. It only shows the cube-generation aspects of the process. The rest of the program looks like the tetrahedron program above. The full source for the program is in the file Cube3D example program.
A. Declare Array. This code declares a real array for the cube points;
real CubePoints;
B. Fill Array. This subroutine fills the array with points for each triangle and face of the cube:
procedure SetCubePoints; begin \Front CubePoints:=[[[-1.0, -1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 1.0, 1.0]], [[-1.0, -1.0, 1.0], [1.0, 1.0, 1.0], [-1.0, 1.0, 1.0]], \Right Side [[1.0, -1.0, 1.0], [1.0, -1.0, -1.0], [1.0, 1.0, -1.0]], [[1.0, -1.0, 1.0], [1.0, 1.0, -1.0], [1.0, 1.0, 1.0]], \Back [[1.0, -1.0, -1.0], [-1.0, -1.0, -1.0], [-1.0, 1.0, -1.0]], [[1.0, -1.0, -1.0], [-1.0, 1.0, -1.0], [1.0, 1.0, -1.0]], \Left Side [[-1.0, -1.0, -1.0], [-1.0, -1.0, 1.0], [-1.0, 1.0, 1.0]], [[-1.0, -1.0, -1.0], [-1.0, 1.0, 1.0], [-1.0, 1.0, -1.0]], \Top [[-1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, -1.0]], [[-1.0, 1.0, 1.0], [1.0, 1.0, -1.0], [-1.0, 1.0, -1.0]], \Bottom [[1.0, -1.0, 1.0], [-1.0, -1.0, 1.0], [-1.0, -1.0, -1.0]], [[1.0, -1.0, 1.0], [-1.0, -1.0, -1.0], [1.0, -1.0, -1.0]] ]; end;
C. Load Cube In Mesh. This subroutine copies the cube points for each triangle into the specified mesh:
procedure BuildCube(Mesh); int Mesh,T; begin Clear3DData(Mesh); for T:=0 to 12-1 do begin Add3DTriangle(Mesh,CubePoints(T,0,0),CubePoints(T,0,1),CubePoints(T,0,2), CubePoints(T,1,0),CubePoints(T,1,1),CubePoints(T,1,2), CubePoints(T,2,0),CubePoints(T,2,1),CubePoints(T,2,2), $00FF00FF); end; Set3DNormals(Mesh,89.0); end;
III. Draw Sphere. This subroutine shows how to build a sphere in EXPL. This example illustrates building a 3D object by calculating the position of rectangle vertices. This technique is used extensively in the Solar System example program.
procedure BuildSphere(Mesh, Size, Sectors,Sections,Color); \ Build an Sphere of the specified size \ Sectors and Sections define how it is sliced up int Mesh; real Size; int Sectors,Sections, Color; int Lat,Long; real P1(3),P2(3),P3(3),P4(3); real ALong,ALat,LongInc,LatInc; define Pi = 3.14159265358979323; define RadToDegree = Pi/180.0;
procedure SpherePoint(Long,Lat,Result); real Long,Lat,Result; begin Long:=Long * RadToDegree; Lat:=Lat * RadToDegree; Result(0):=Sin(Long) * Sin(Lat) * Size; Result(1):=Cos(Long) * Sin(Lat) * Size; Result(2):=Cos(Lat) * Size; end;
begin LongInc:=360.0/FLoat(Sectors); LatInc:=180.0/FLoat(Sections); for Lat:=0 to Sections-1 do for Long:=0 to Sectors-1 do begin ALong:=FLoat(Long) * LongInc; ALat:=FLoat(Lat) * LatInc; SpherePoint(ALong,ALat,P1); SpherePoint(ALong+LongInc,ALat,P2); SpherePoint(ALong+LongInc,ALat+LatInc,P3); SpherePoint(ALong,ALat+LatInc,P4); Add3DRectangle(Mesh,P1(0),P1(1),P1(2),P2(0),P2(1),P2(2),P3(0),P3(1),P3(2),P4(0),P4(1),P4(2),Color); end; end;
IV. Hit Testing. This code fragment shows you need do Hit Testing. The subroutines test to see if the specified X,Y coordinate falls on a mesh. If it does, the subroutine colors the triangle's nearest coordinate blue.
The heart of the subroutine is the Test3DHit intrinsic that returns true if a screen pixel is directly over a mesh. If the result is true, the intrinsic returns the handle of the mesh and the index of the individual triangle intersected by the pixel.
procedure DoHitTest(X,Y); \Test if X,Y hits mesh face \Color if it does int X,Y; int Hit,Handle,Inx; begin X:=X-ViewLeft; Y:=Y-ViewTop; Hit:=Test3DHit(X,Y,@Handle,@Inx); if Hit then begin Set3DItemColor(Handle,Inx,RGBToColor(0,0,255,255),RGBToColor(0,0,255,255),RGBToColor(0,0,255,255)); end; end;
Note that the pixel's position is relative to the upper-left corner of the 3D window. In this subroutine the upper-left corner of the window is represented by the variables ViewLeft and ViewTop. This subroutine is used in the Torus example program.
V. Show Background Bitmap. It is often useful to use an image as a background to a 3D scene. For example, you might want to place a picture of stars in the night sky behind a 3D representation of a planet. For this reason, EXPL has intrinsics that can put bitmap images behind a scene in the 3D window. This technique is used extensively in the Solar System example program.
A. Declare Bitmap Handle. EXPL already has the ability to load bitmap images. The 3D background image feature piggybacks on the regular bitmap feature. The first step is to declare a handle for the background bitmap:
int BackBitmap;
B. Get A Bitmap Handle. The next step is to get a handle for the bitmap. The following code illustrates using the AllocateBitmap intrinsic to create a bitmap handle. Once the handle's value is stored in a variable, the variable can be used to access the bitmap anytime you want.
BackBitmap:=AllocateBitmap;
C. Load Bitmap. Once you have the handle, you load a bitmap file into the handle. The following code illustrates using the LoadBitmap intrinsic to pull a bitmap file into memory, making it available for future operations. The bitmap can be any standard bitmap type.
LoadBitmap(BackBitmap,"StarrySky.jpg");
D. Display Bitmap. Once you have a bitmap loaded into memory, it can be displayed in the background of the 3D window using the Set3DBackground intrinsic. This intrinsic sets the position, scaling and depth of the image:
Set3DBackground(BackBitmap,true,-320.0,-190.0,-20.0,1.15,1.1);
III. Applying Textures. Textures are one of the most powerful techniques for making realistic 3D objects. With a texture you can apply a bitmap to the surface of 3D object. The bitmap enables you to paint the object with fine, photographic details that make it look almost like a real-world object. In this example we will apply a photograph of the Earth to a sphere to produce a realistic 3D image of the Earth. This technique is used extensively in the Solar System example program.
A. Declare Bitmap Handle. EXPL already has the ability to load bitmap images. The texture feature piggybacks on the regular bitmap feature. The first step is to declare a handle for the Earth bitmap.
int EarthMap;
B. Get A Bitmap Handle. The next step is to get a handle for the bitmap. The following code illustrates using the AllocateBitmap intrinsic to create a bitmap handle. Once the handle's value is stored in a variable, the variable can be used to access the bitmap anytime you want.
EarthMap:=AllocateBitmap;
C. Load Bitmap. Once you have the handle, you load a bitmap file into the handle. The following code illustrates using the LoadBitmap intrinsic to pull a bitmap file into memory, making it available for future operations. The bitmap can be any standard bitmap type.
LoadBitmap(EarthMap,"EarthMap.jpg");
D. Apply Texture. Once you've loaded the texture bitmap, you can apply it to a mesh using the Set3DTexture intrinsic. In this case the mesh is a sphere that was created using the technique illustrated in in example III above. The texture can be mapped on to the surface of the object in several different ways, depending on the effect you are trying to create. In this case we are using Auto Mode and the Sphere Map sub-mode:
Set3DTexture(EarthMesh,1,1,@EarthMap,1);
Next, we set the parameter appropriate for this mode of texturing using the Set3DTextureParams intrinsic. In this example, we set the scale and offset of the texture to values appropriate for the texture mode, the size of the image and the size of the object:
Set3DTextureParams(EarthMesh,0, 1.0, 0.5, 0.0, 0.0); Set3DTextureParams(EarthMesh,1, 0.0, 0.5, 0.0, 0.0);
Finally, we use the Set3DTextureFlags intrinsic to enable the texture:
Set3DTextureFlags(EarthMesh, 0, true);
|