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/
  Nice links to have:
  - Anim8or homepage good 3D modeler
  - DOGA Homepage another good free 3D modeler
  - CONV3DS.EXE converts .3DS files to .X files
  - 3DCafe.com thousands of free 3D models available
  - Microsoft's DirectX homepage learn more, download their SDK documentation
  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).

  Prev Chapter | Contents | Next Chapter