Jump to content

3d Graphics using Matrices


Malkey
 Share

Recommended Posts

I was looking through a book on Elementary Linear Algebra, as we all do from time to time, and came across a section on Computer Graphics. The following is the result.

Drag Left mouse up or down Rotates around the X-axis.

Drag Left mouse left or right Rotates around the Y-axis.

The book calls the figure a truncated pyramid.

The calculations use the X, Y, Z coordinates stored in $pts,

The display uses only the X, Y coordinates i.e. $pts[n][0], and $pts[n][1]

#include <GUIConstants.au3>
#Include <Misc.au3>

Global $pts[12][3] = [ [1, -0.8, 0], [0.5, -0.8, -0.866], [ -.5, -.8, -.866], [ -1, -.8, 0], [ -.5, -.8, .866], _
        [.5, -.8, .866], [.84, -.4, 0], [.315, .125, -.546], [ -.21, .65, -.364], [ -.36, .8, 0], [ -.21, .65, .364], [.315, .125, .546] ]
Global Const $nPI = 3.1415926535897932384626433832795

Global $user32_dll = DllOpen("user32.dll")
Global $fact = 200, $angYaxis = 0, $angXaxis = 0
Local $hGraph, $mouseDiffX, $mouseDiffY, $msg

$gui = GUICreate("3d Display", 640, 640)
GUISetBkColor(0xFFFFF0)
Draw2D()
GUISetState()
While 1  ; ESC key
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If _IsPressed("01", $user32_dll) Then  ; Virtual-Key Code (0x01) Left mouse button
        $angYaxis = 0
        $mouseDiffX = 0
        $MouseStartPos = MouseGetPos()
        While _IsPressed("01", $user32_dll)    ; Virtual-Key Code (0x01) Left mouse button
            $pos = MouseGetPos()
            $mouseDiffX = Int(($pos[0] - $MouseStartPos[0]) / 10)
            $mouseDiffY = Int(($pos[1] - $MouseStartPos[1]) / 10)
            If Abs($mouseDiffX) > 0 Then
                $angXaxis = Mod($mouseDiffX, 360)               
                $pts = rotateYaxis(-$angXaxis * $nPI / 180)
                GUICtrlDelete($hGraph)
                Draw2D()
            EndIf
            If Abs($mouseDiffY) > 0 Then
                $angYaxis = Mod($mouseDiffY, 360)
                $pts = rotateXaxis($angYaxis * $nPI / 180)
                GUICtrlDelete($hGraph)
                Draw2D()
            EndIf
            ;ConsoleWrite("$angYaxis=" & $angYaxis & "    $angXaxis=" & $angXaxis & @CRLF)
            Sleep(50)
        WEnd
    EndIf ; mouse BTN 1 pressed??
    Sleep(10)
WEnd

Func rotateYaxis($ang)
    Local $RotYMat[3][3] = [[ Cos($ang), 0, Sin($ang) ], [ 0, 1, 0 ], [ -Sin($ang), 0, Cos($ang) ]]
    $pts = ArrayProduct($pts, $RotYMat)
    Return $pts
EndFunc   ;==>rotateYaxis

Func rotateXaxis($ang)
    Local $RotXMat[3][3] = [[1, 0, 0], [0, Cos($ang), -Sin($ang) ], [0, Sin($ang), Cos($ang) ]]
    $pts = ArrayProduct($pts, $RotXMat)
    Return $pts
EndFunc   ;==>rotateXaxis

Func Draw2D()
    $hGraph = GUICtrlCreateGraphic(320, 320, 0, 0)
    GUICtrlSetGraphic($hGraph, $GUI_GR_PENSIZE, 3)
    Sleep(10)
    For $xDisp = 1 To 6 - 1
        ;MsgBox(0,"",$pts[$xDisp-1][0])
        GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[$xDisp - 1][0] * $fact, $pts[$xDisp - 1][1] * $fact)
        GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x0000ff)
        GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[$xDisp][0] * $fact, $pts[$xDisp][1] * $fact)
    Next
    GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[5][0] * $fact, $pts[5][1] * $fact)
    GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x0000ff)
    GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[0][0] * $fact, $pts[0][1] * $fact)
    For $xDisp = 7 To 12 - 1
        GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[$xDisp - 1][0] * $fact, $pts[$xDisp - 1][1] * $fact)
        GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x00ffff)
        GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[$xDisp][0] * $fact, $pts[$xDisp][1] * $fact)
    Next
    GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[11][0] * $fact, $pts[11][1] * $fact)
    GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x00ffff)
    GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[6][0] * $fact, $pts[6][1] * $fact)
    For $xDisp = 1 To 6 - 1
        GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[$xDisp - 1][0] * $fact, $pts[$xDisp - 1][1] * $fact)
        GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x00ff00)
        GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[$xDisp + 5][0] * $fact, $pts[$xDisp + 5][1] * $fact)
    Next
    GUICtrlSetGraphic($hGraph, $GUI_GR_MOVE, $pts[5][0] * $fact, $pts[5][1] * $fact)
    GUICtrlSetGraphic($hGraph, $GUI_GR_COLOR, 0x00ff00)
    GUICtrlSetGraphic($hGraph, $GUI_GR_LINE, $pts[11][0] * $fact, $pts[11][1] * $fact)
    GUICtrlSetGraphic($hGraph, $GUI_GR_REFRESH, 3)
    Sleep(50)
    Return
EndFunc   ;==>Draw2D

;==========================================================================
; Function:    ArrayProduct (modified mod added)
; Purpose:   Calculate the ordinary matrix product of two matricies, as described at:
;           en.wikipedia.org/wiki/Matrix_multiplication#Ordinary_matrix_product
; Call with:    _ArrayProduct( $avA, $avB )
;   Where:       $avA and $avB are 2D arrays of numbers where the
;           row count (depth) of $avA matches the column count of $avB
; On success:   Returns a 2D array (product matrix)
; On failure:   Returns 0 and sets @error and @extended for invalid inputs
;==========================================================================
Func ArrayProduct($avA, $avB, $m = 0)
    ; Check for parameter errors.
    If IsArray($avA) = 0 Or IsArray($avB) = 0 Then Return SetError(1, 1, 0) ; both must be arrays
    If UBound($avA, 0) <> 2 Or UBound($avB, 0) <> 2 Then Return SetError(1, 2, 0) ; both must be 2D arrays
    If UBound($avA, 2) <> UBound($avB) Then Return SetError(1, 3, 0) ; depth must match

    ; Create return array
    Local $iRows = UBound($avA), $iCols = UBound($avB, 2), $iDepth = UBound($avA, 2)
    Local $avRET[$iRows][$iCols]

    ; Calculate values
    For $r = 0 To $iRows - 1
        For $c = 0 To $iCols - 1
            $x = 0
            For $z = 0 To $iDepth - 1
                $x += ($avA[$r][$z] * $avB[$z][$c])
            Next
            $avRET[$r][$c] = $x
        Next
    Next
    Return $avRET
EndFunc   ;==>ArrayProduct

It is just an example.

Link to comment
Share on other sites

I was looking through a book on Elementary Linear Algebra, as we all do from time to time, and came across a section on Computer Graphics. The following is the result.

Drag Left mouse up or down Rotates around the X-axis.

Drag Left mouse left or right Rotates around the Y-axis.

The book calls the figure a truncated pyramid.

The calculations use the X, Y, Z coordinates stored in $pts,

The display uses only the X, Y coordinates i.e. $pts[n][0], and $pts[n][1]

It is just an example.

A very nice example demonstrating how to calculate and manipulate 3D objects. I'm sure I will have uses for some of those functions in the future.

What was the name of the book?

If your interested in this sort of stuff then 'Computational Geometry in C' by Joseph O'Rouke has some interesting example that can be converted into AutoIt quite easily I used some of them in other flavours of BASIC.

Bowmore

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

Nice! Really good!

Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator

VW Bug user

Pinheiral (Pinewood) city:

http://pt.wikipedia.org/wiki/Pinheiral

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...