Rapid-Q Documentation by William Yu (c)1999 |
Chapter 13 |
 |
13. Direct3D for Rapid-Q
This is only an introduction to using Direct3D with Rapid-Q. Since most of
the Direct3D components have not yet been finalized under Rapid-Q, this chapter
will deal mostly with what can be done.
13.1 Requirement specifications
The most basic requirement is that you have the DirectX 6.0 runtimes.
If you're unsure what version you have, type DXDIAG at the command prompt,
or find the file under C:\WINDOWS\SYSTEM. If you don't have DXDIAG then you'll
definitely need to upgrade. You can download the runtime files at
http://msdn.microsoft.com/directx/
Just the runtime files, you don't need the SDK, but if you want, no one is stopping
you from downloading it. The SDK does contain an important file CONV3DS.EXE which
is necessary to convert different 3D models for use with your programs.
However, I have posted a link to this file so it's not necessary for you download
the entire SDK just for that one file.
Other nice things to have:
 | 3D accelerated video card
 | A 3D modeler (like 3D Studio)
 | OpenGL (some 3D modelers use this)
| | |
Even if you don't have any of the above, this shouldn't matter.
A 3D card is not necessary, but you'll find that running your programs can be
5 to 10 times slower, but still manageable if you have a good Pentium.
I don't have a 3D card, and only get about 5-10 fps on my P200, but it doesn't
bother me. If you don't have a 3D modeling program don't worry, there's some
free 3D modelers on the internet. I find that Anim8or is pretty good,
for something that's completely free there's nothing to complain about.
It's only a 500KB download, which is very small compared to other 3D modeling
programs I've seen. It does require OpenGL, but check your C:\WINDOWS\SYSTEM
directory for OPENGL32.DLL. If you have it, you're in good shape, if not, just
download it off the web at http://www.opengl.org/
13.2 Using Anim8or to create 3D models
If you already have a good understanding of how to create 3D models, you can
skip this section. I will be using Anim8or to demonstrate simple 3D modeling
which you can quickly use in your Rapid-Q programs. If you haven't already downloaded
Anim8or's HTML documentation, I suggest you do that. I won't cover all there is
to know about Anim8or, just the basics.
Step by step introduction
 | Load Anim8or
 | Click on a polygon object
 | To draw this object, just click and drag your mouse on the main grid
 | Make sure to also center the object (not necessary but a good thing anyway).
To do this, just select the object you want centered, then select from the
menu:
Edit|Locate|Center about origin
 | Make sure you haven't drawn an overly big polygon, perhaps the size of your pinky
is good enough.
 | Now to export your object, select from the menu: Object|Export
Just make sure to save as a .3DS file.
 | Let's just say you named your file poly.3ds then from the command
prompt type in:
CONV3DS -m poly.3ds
I assumed you downloaded CONV3DS.EXE (copy this to your Windows directory
if you want).
 | Once converted, you should have a poly.x file, this object file can
now be used in your Rapid-Q program!
| | | | | | | |
If you don't like doing your own 3D models you can always download pre-made
3D models from www.3dcafe.com and other websites like it. However, it's always nice
to customize your objects, so learning to use a 3D modeling program wouldn't hurt.
The optional parameter -m is used to create a single mesh for use with MeshBuilder.
Without -m, your .X file is saved as a frame so you would have to use QD3DFrame
to load your .X file.
13.3 Loading/Using .X Files
Simply loading an .X file is easy enough, to make sure you have this
much working, copy and paste this code:
' Simply places an object on the scene
$TYPECHECK ON
CONST alClient = 5
'-- Light Types
CONST D3DRMLIGHT_AMBIENT = 0
CONST D3DRMLIGHT_POINT = 1
CONST D3DRMLIGHT_SPOT = 2
CONST D3DRMLIGHT_DIRECTIONAL = 3
CONST D3DRMLIGHT_PARALLELPOINT = 4
DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired
DIM DXTimer AS QDXTimer
DXTimer.Enabled = 1
DXTimer.Interval = 0
DXTimer.Activeonly = 0
DXTimer.OnTimer = DXTimerExpired
CREATE Form AS QForm
Caption = "Direct 3D Example"
Center
CREATE DXScreen AS QDXScreen
Init(320,240)
Align = alClient
Use3D = 1
UseHardware = 0 '' This is for non-3D accelerated video cards.
'' 3D will be emulated using software, which
'' is much slower.
OnInitialize = DXInitialize
END CREATE
ShowModal
END CREATE
SUB DXInitialize(Sender AS QDXScreen)
DIM Light AS QD3DLight
DIM LightFrame AS QD3DFrame, MeshFrame AS QD3DFrame
DIM MeshBuilder AS QD3DMeshBuilder
DXScreen.CreateFrame(LightFrame)
DXScreen.CreateFrame(MeshFrame)
'-- Need light, else object would be completely hidden
DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, Light)
LightFrame.AddLight(Light)
DXScreen.SetCameraPosition(-5, 10, 0)
DXScreen.SetCameraOrientation(0.35, -0.65, 1.0, -0.15, 1.0, 0.5)
MeshFrame.SetPosition(0, 0, 15)
MeshFrame.SetOrientation(0, 0, 1, 0, 1, 0)
MeshFrame.SetRotation(0, 0, 0, 0.05) '-- Angle of rotation = 0.05
DXScreen.CreateMeshBuilder(MeshBuilder) '-- Create object
MeshBuilder.Load("poly.x") '-- Load your object
MeshFrame.AddVisual(MeshBuilder) '-- Add object to frame
END SUB
SUB DXTimerExpired
DXScreen.ForceUpdate(0,0,50,50) '-- Updates FPS Text
DXScreen.Render
DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
DXScreen.Flip
END SUB
If everything worked, you should obtain some output that looks like this:

If you understood the example, it's quite easy to add more objects to the scene,
just create another MeshFrame and load another object file. Play around with the
code until you're satisfied.
13.4 Wrapping textures around an object
Now that we have the basics, time to wrap textures around our object.
To do this, all we need is a .BMP file for our texture. There's a few important
points to note, First, width and height of bitmap must be equal, and secondly, they must
be powers of 2 (ie. 32x32, 256x256, etc.). This is obviously for optimization reasons,
but don't ask me, I didn't create Direct3D. Anyway, to wrap this texture around our
object, we just need to modify the above code a bit (changes are noted in Blue):
' Wrap textures around 3D object
$TYPECHECK ON
CONST alClient = 5
'-- Light Types
CONST D3DRMLIGHT_AMBIENT = 0
CONST D3DRMLIGHT_POINT = 1
CONST D3DRMLIGHT_SPOT = 2
CONST D3DRMLIGHT_DIRECTIONAL = 3
CONST D3DRMLIGHT_PARALLELPOINT = 4
'-- Wrap Types
CONST D3DRMWRAP_FLAT = 0
CONST D3DRMWRAP_CYLINDER = 1
CONST D3DRMWRAP_SPHERE = 2
CONST D3DRMWRAP_CHROME = 3
CONST D3DRMWRAP_SHEET = 4
CONST D3DRMWRAP_BOX = 5
CONST WrapType = D3DRMWRAP_SPHERE '-- You can modify this
DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired
DIM DXTimer AS QDXTimer
DXTimer.Enabled = 1
DXTimer.Interval = 0
DXTimer.Activeonly = 0
DXTimer.OnTimer = DXTimerExpired
CREATE Form AS QForm
Caption = "Direct 3D Example"
Center
CREATE DXScreen AS QDXScreen
Init(320,240)
Align = alClient
Use3D = 1
UseHardware = 0 '' This is for non-3D accelerated video cards.
'' 3D will be emulated using software, which
'' is much slower.
OnInitialize = DXInitialize
END CREATE
ShowModal
END CREATE
SUB DXInitialize(Sender AS QDXScreen)
DIM Light AS QD3DLight
DIM LightFrame AS QD3DFrame, MeshFrame AS QD3DFrame
DIM MeshBuilder AS QD3DMeshBuilder
DIM Texture AS QD3DTexture
DIM Wrap AS QD3DWrap
DIM Mesh AS QD3DMesh
DXScreen.CreateFrame(LightFrame)
DXScreen.CreateFrame(MeshFrame)
DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, Light)
LightFrame.AddLight(Light)
DXScreen.SetCameraPosition(-5, 10, 0)
DXScreen.SetCameraOrientation(0.35, -0.65, 1.0, -0.15, 1.0, 0.5)
MeshFrame.SetPosition(0, 0, 15)
MeshFrame.SetOrientation(0, 0, 1, 0, 1, 0)
MeshFrame.SetRotation(0, 0, 0, 0.05) ' Angle of rotation = 0.05
DXScreen.CreateMeshBuilder(MeshBuilder)
MeshBuilder.Load("poly.x") '-- Egg object
MeshBuilder.LoadTexture("back.bmp") '-- New lines
MeshBuilder.CreateMesh(Mesh)
MeshFrame.AddVisual(Mesh)
DXScreen.CreateWrap(WrapType, 0,0,0, 0,0,1, 0,1,0, 0,0, 1,1, Wrap)
Wrap.Apply(Mesh)
END SUB
SUB DXTimerExpired
DXScreen.ForceUpdate(0,0,50,50)
DXScreen.Render
DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
DXScreen.Flip
END SUB
Again, if everything worked, you should obtain some output that looks like this (depending
on what texture file you used of course):

As you can see, it doesn't take much to add textures to our objects.
The only problem is you lose a few frame rates by doing this.
13.5 Rotating/Moving objects
Unfortunately as of this writing, there is no support for Animation sets, but
that will be worked on later. You can do simple rotations and scene movements just
by calling the method Move or manually setting the camera angles and
positions. Using the example from above, add this extra code:
DXScreen.ForceUpdate(0,0,50,50)
DXScreen.Move(1) '-- Add this line
DXScreen.Render
This moves the camera position by the amount specified. The affect is a rotation
about angle Theta. This Theta was specified on the line:
MeshFrame.SetRotation(0, 0, 0, 0.05) ' Angle of rotation = 0.05
DXScreen.Move animates the entire scene, to just animate a certain frame, you
can use MeshFrame.Move(1).
