' Direct 3D example with Shadowed object for Rapid-Q by William Yu
' Move your mouse up/down to see the shadow increase/decrease

$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

'-- Renderer modes
CONST D3DRMRENDERMODE_BLENDEDTRANSPARENCY = 1
CONST D3DRMRENDERMODE_SORTEDTRANSPARENCY = 2
CONST D3DRMRENDERMODE_LIGHTINMODELSPACE = 8
CONST D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR = 16
CONST D3DRMRENDERMODE_DISABLESORTEDALPHAZWRITE = 32

'-- Shades
CONST D3DRMSHADE_FLAT = 0
CONST D3DRMSHADE_GOURAUD = 1
CONST D3DRMSHADE_PHONG = 2
CONST D3DRMSHADE_MASK = 7
CONST D3DRMSHADE_MAX = 8

CONST D3DRMLIGHT_OFF = 0
CONST D3DRMLIGHT_ON = 8
CONST D3DRMLIGHT_MASK = 56
CONST D3DRMLIGHT_MAX = 64

CONST D3DRMFILL_POINTS = 0
CONST D3DRMFILL_WIREFRAME = 64
CONST D3DRMFILL_SOLID = 128
CONST D3DRMFILL_MASK = 448
CONST D3DRMFILL_MAX = 512

'-- Shade quality
CONST D3DRMRENDER_WIREFRAME = D3DRMSHADE_FLAT + D3DRMLIGHT_OFF + D3DRMFILL_WIREFRAME
CONST D3DRMRENDER_UNLITFLAT = D3DRMSHADE_FLAT + D3DRMLIGHT_OFF + D3DRMFILL_SOLID
CONST D3DRMRENDER_FLAT = D3DRMSHADE_FLAT + D3DRMLIGHT_ON + D3DRMFILL_SOLID
CONST D3DRMRENDER_GOURAUD = D3DRMSHADE_GOURAUD + D3DRMLIGHT_ON + D3DRMFILL_SOLID
CONST D3DRMRENDER_PHONG = D3DRMSHADE_PHONG + D3DRMLIGHT_ON + D3DRMFILL_SOLID


DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXInitializeSurface(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired
DECLARE SUB DXMouseMove (X AS INTEGER, Y AS INTEGER)

DIM DXTimer AS QDXTimer
    DXTimer.Enabled = 1
    DXTimer.Interval = 0
    DXTimer.OnTimer = DXTimerExpired

DIM SphereFrame AS QD3DFrame


CREATE Form AS QForm
    Caption = "Direct 3D Example"
    Center
    CREATE DXScreen AS QDXScreen
        Init(320,240)
        Align = alClient
        Use3D = 1
        UseHardware = 1        '' This is for non-3D accelerated video cards.
                               '' 3D will be emulated using software, which
                               '' is much slower.
        OnInitialize = DXInitialize
        OnInitializeSurface = DXInitializeSurface
        OnMouseMove = DXMouseMove
    END CREATE
    ShowModal
END CREATE


SUB DXInitialize(Sender AS QDXScreen)
   DIM Light AS QD3DLight
   DIM LightFrame AS QD3DFrame, SceneFrame AS QD3DFrame
   DIM PlaneFrame AS QD3DFrame
   DIM SceneMeshBuilder AS QD3DMeshBuilder, ObjectMesh AS QD3DMeshBuilder
   DIM Shadow AS QD3DVisual

   DXScreen.CreateMeshBuilder(SceneMeshBuilder)
   DXScreen.CreateMeshBuilder(ObjectMesh)

   DXScreen.CreateFrame(LightFrame)
   DXScreen.CreateFrame(SceneFrame)
   DXScreen.CreateFrame(PlaneFrame)
   DXScreen.CreateFrame(SphereFrame)

   DXScreen.SetCameraPosition(0, 5, -30)
   DXScreen.SetCameraOrientation(0, 0, 1, 0, 1, 0)

   DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 0.9, 0.9, 0.9, Light)
   DXScreen.AddLight(Light)

   DXScreen.CreateLightRGB(D3DRMLIGHT_SPOT, 1, 1, 1, Light)
   Light.SetPenUmbra(0.2)
   Light.SetUmbra(0.15)
   Light.SetRange(40)

   SceneMeshBuilder.Load("plane.x")
   SceneMeshBuilder.Scale(3,3,3)
   SceneFrame.AddVisual(SceneMeshBuilder)

   ObjectMesh.Load("sphere.x")
   ObjectMesh.Scale(0.5,0.5,0.5)

   DXScreen.CreateShadow(ObjectMesh, Light, 0, 1, 0, 0, 1, 0, Shadow)

   LightFrame.AddLight(Light)
   LightFrame.SetPosition(0,10,0)
   SphereFrame.AddVisual(Shadow)
   SphereFrame.AddVisual(ObjectMesh)
   SphereFrame.SetPosition(0,5,0)

   'SceneMeshBuilder.SetQuality(D3DRMRENDER_WIREFRAME)
   'ObjectMesh.SetQuality(D3DRMRENDER_WIREFRAME)
END SUB

SUB DXInitializeSurface(Sender AS QDXScreen)
   DXScreen.SetRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY OR D3DRMRENDERMODE_SORTEDTRANSPARENCY)
END SUB

SUB DXTimerExpired
   DXScreen.ForceUpdate(0,0,40,40)    ' Update FPS text only
   DXScreen.Render
'   DXScreen.Move(1)
   DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
   DXScreen.Flip
END SUB

SUB DXMouseMove (X AS INTEGER, Y AS INTEGER)
   SphereFrame.SetPosition(0, -(Y-100)/5, 0)
   DXScreen.Render
END SUB

