' Direct3D model viewer for Rapid-Q by William Yu 
' Only loads mesh objects. 

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

'-- 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

'-- 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


DECLARE SUB dxInitialize(sender AS QDXSCREEN)
DECLARE SUB dxInitializeSurface(sender AS QDXSCREEN)
DECLARE SUB dxTimerExpired
DECLARE SUB exitItemClick(sender AS QMENUITEM)
DECLARE SUB openItemClick(sender AS QMENUITEM)
DECLARE SUB rotateButtonClick(sender AS QBUTTON)
DECLARE SUB rotateStopButtonClick(sender AS QBUTTON)
DECLARE SUB upButtonMouseDown(button%, x%, y%, shift%, sender AS QBUTTON)
DECLARE SUB upButtonMouseUp(button%, x%, y%, shift%, sender AS QBUTTON)
DECLARE SUB textureButtonClick(sender AS QBUTTON)

DIM dxTimer AS QDXTIMER
    dxTimer.enabled = 1
    dxTimer.interval = 0
    dxTimer.activeOnly = 0
    dxTimer.onTimer = dxTimerExpired
DIM frameView AS DOUBLE
    frameView = 10
DIM wrapType AS LONG
    wrapType = D3DRMWRAP_SPHERE
DIM T! AS SINGLE
DIM meshFrame AS QD3DFRAME
DIM meshBuilder AS QD3DMESHBUILDER
DIM wrap AS QD3DWRAP


CREATE form AS QFORM
    caption = "Direct3D Model Viewer"
    width = 640
    height = 480
    center
    CREATE panel AS QPANEL
        width = 150
        align = alRight
        bevelOuter = bvLowered
        CREATE upButton AS QBUTTON
            caption = "/\"
            hint = "up"
            width = 30
            left = 60
            top = 10
            tabOrder = 0
            onMouseDown = upButtonMouseDown
            onMouseUp = upButtonMouseUp
        END CREATE
        CREATE downButton AS QBUTTON
            caption = "\/"
            hint = "down"
            left = 60
            width = 30
            top = 40
            tabOrder = 0
            onMouseDown = upButtonMouseDown
            onMouseUp = upButtonMouseUp
        END CREATE
        CREATE textureImage AS QIMAGE
            left = 25
            width = 100
            top = 70
            onClick = textureButtonClick
        END CREATE
        CREATE textureButton AS QBUTTON
            caption = "Texture..."
            left = 50
            width = 60
            top = 180
            onClick = textureButtonClick
        END CREATE
        CREATE rotateLabelAngle AS QLABEL
            top = 273
            left = 15
            caption = "Angle:"
        END CREATE
        CREATE rotateEditAngle AS QEDIT
            top = 270
            left = 60
            width = 40
            text = "1"
        END CREATE
        CREATE rotateLabelX AS QLABEL
            top = 303
            left = 15
            caption = "X:"
        END CREATE
        CREATE rotateEditX AS QEDIT
            top = 300
            left = 60
            width = 40
            text = "1"
        END CREATE
        CREATE rotateLabelY AS QLABEL
            top = 333
            left = 15
            caption = "Y:"
        END CREATE
        CREATE rotateEditY AS QEDIT
            top = 330
            left = 60
            width = 40
            text = "1"
        END CREATE
        CREATE rotateLabelZ AS QLABEL
            top = 363
            left = 15
            caption = "Z:"
        END CREATE
        CREATE rotateEditZ AS QEDIT
            top = 360
            left = 60
            width = 40
            text = "1"
        END CREATE
        CREATE rotateButton AS QBUTTON
            left = 10
            top = 390
            width = 60
            caption = "&Rotate"
            onClick = rotateButtonClick
        END CREATE
        CREATE rotateStopButton AS QBUTTON
            left = 80
            top = 390
            width = 60
            caption = "&Stop"
            onClick = rotateStopButtonClick
        END CREATE
    END CREATE
    CREATE dxScreen AS QDXSCREEN
        align = alClient
        bitCount = 16
        use3D = 1
        useHardware = 0
        onInitialize = dxInitialize
        onInitializeSurface = dxInitializeSurface
    END CREATE
    CREATE mainMenu AS QMAINMENU
        CREATE fileMenu AS QMENUITEM
            caption = "&File"
            CREATE openItem AS QMENUITEM
                caption = "&Open..."
                onClick = openItemClick
            END CREATE
            CREATE breakItem1 AS QMENUITEM
                caption = "-"
            END CREATE
            CREATE exitItem AS QMENUITEM
                caption = "E&xit"
                onClick = exitItemClick
            END CREATE
        END CREATE
    END CREATE
    showModal
END CREATE



SUB exitItemClick(sender AS QMENUITEM)
    form.close
END SUB


SUB openItemClick(sender AS QMENUITEM)
    DIM openDialog AS QOPENDIALOG

    openDialog.filter = "*.x (X models)|*.x"
    IF openDialog.execute THEN
       '-- Remove previous object from frame 
       meshFrame.deleteVisual(meshBuilder)
       '-- Rebuilds mesh, removing the old object 
       dxScreen.createMeshBuilder(meshBuilder)
       '-- Load a new object 
       meshBuilder.load(openDialog.fileName)
       '-- Add this new object to the frame 
       meshFrame.addVisual(meshBuilder)
    END IF
END SUB


SUB textureButtonClick(sender AS QBUTTON)
    DIM openDialog AS QOPENDIALOG

    openDialog.filter = "*.bmp (Bitmap files)|*.bmp"
    IF openDialog.execute THEN
        textureImage.BMP = openDialog.fileName
        meshBuilder.loadTexture(openDialog.fileName)
        dxScreen.createWrap(wrapType, 0,0,0, 0,0,1, 0,1,0, 0,0, 1,1, wrap)
        wrap.apply(meshBuilder)
    END IF
END SUB


SUB upButtonMouseDown(button%, x%, y%, shift%, sender AS QBUTTON)
    DEFSNG T!

    T! = TIMER
    IF button% = 0 THEN
        sender.tabOrder = 0
        DO
            IF sender.hint = "up" THEN
                INC(frameView)
            ELSE
                DEC(frameView)
            END IF
            meshFrame.setPosition(0, 0, frameView)
            doEvents
            dxTimerExpired
        LOOP UNTIL sender.tabOrder = 1
    END IF
END SUB

SUB upButtonMouseUp(button%, x%, y%, shift%, sender AS QBUTTON)
    IF button% = 0 THEN
        sender.tabOrder = 1
    END IF
END SUB


SUB rotateButtonClick(sender AS QBUTTON)
    meshFrame.setRotation(VAL(rotateEditX.text), _
                          VAL(rotateEditY.text), _
                          VAL(rotateEditZ.text), _
                          VAL(rotateEditAngle.text)/10)
END SUB


SUB rotateStopButtonClick(sender AS QBUTTON)
    meshFrame.setRotation(0, 0, 0, 0)
END SUB


SUB dxInitialize(sender AS QDXSCREEN)
   DIM light AS QD3DLIGHT, ambient AS QD3DLIGHT
   DIM lightFrame AS QD3DFRAME

   dxScreen.createFrame(lightFrame)
   dxScreen.createFrame(meshFrame)

   dxScreen.createLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, light)
   lightFrame.addLight(Light)

   dxScreen.createLightRGB(D3DRMLIGHT_AMBIENT, 0.1, 0.1, 0.1, ambient)
   dxScreen.addLight(ambient)

   meshFrame.setPosition(0, 0, frameView)

   dxScreen.setCameraPosition(0, 0, 0)
END SUB


SUB dxInitializeSurface(sender AS QDXSCREEN)
   dxScreen.setRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY OR D3DRMRENDERMODE_SORTEDTRANSPARENCY)
END SUB


SUB dxTimerExpired
   dxScreen.forceUpdate(0,0,50,40)    '-- Update FPS text only 
   meshFrame.Move(1)                  '-- This does the animation 
   dxScreen.render
   dxScreen.textOut(10,10,"FPS: "+str$(dxTimer.frameRate), &HFFFFFF, -1)
   dxScreen.flip
END SUB