D3DX Replacement Functions

Share your advanced PureBasic knowledge/code with the community.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

D3DX Replacement Functions

Post by traumatic »

Code updated For 5.20+

I found the following code on my HD, maybe some of you find this useful.
I did this because I hate DLLs and overblown libs...
It has initially been written for DX8, but should of course also work for other versions (it's just math anyway) ...

Note that this is only about the matrix-functions (and only some of them). Well, hope you'll get the idea.

Whatever... provided 'as is':


Code: Select all

;
; D3DpbMATRIX.pb :: D3DX8 - Matrix Replacement Functions
;
; traumatic! '03
;
;
;

;
; ------------------------------------------------------------
;

Structure D3DpbMATRIX
  _11.f : _12.f : _13.f : _14.f
  _21.f : _22.f : _23.f : _24.f
  _31.f : _32.f : _33.f : _34.f
  _41.f : _42.f : _43.f : _44.f
EndStructure


Structure D3DpbVECTOR3
  x.f
  y.f
  z.f
EndStructure

;
; ------------------------------------------------------------
;

;
; vector functions
;
Declare.f D3DpbMagnitude(*v.D3DpbVECTOR3)
Declare   D3DpbNormalize(*v.D3DpbVECTOR3)
Declare.f D3DpbDot(*v1.D3DpbVECTOR3, *v2.D3DpbVECTOR3) 
Declare   D3DpbCross(*out.D3DpbVECTOR3, *v1.D3DpbVECTOR3, *v2.D3DpbVECTOR3)
Declare   D3DpbSubstract(*dst.D3DpbVECTOR3, *a.D3DpbVECTOR3, *b.D3DpbVECTOR3)


;
; matrix functions
;
Declare D3DpbMatrixLookAtLH(*out.D3DpbMATRIX, *eye.D3DpbVECTOR3, *at.D3DpbVECTOR3, *up.D3DpbVECTOR3)
Declare D3DpbMatrixOrthoLH(*out.D3DpbMATRIX, w.f, h.f, zn.f, zf.f)
Declare D3DpbMatrixPerspectiveFovLH(*out.D3DpbMATRIX, fov.f, aspect.f, zn.f, zf.f)
Declare D3DpbMatrixPerspectiveLH(*out.D3DpbMATRIX, w.f, h.f, zn.f, zf.f)
Declare D3DpbMatrixRotationX(*out.D3DpbMATRIX, angle.f)
Declare D3DpbMatrixRotationY(*out.D3DpbMATRIX, angle.f)
Declare D3DpbMatrixRotationZ(*out.D3DpbMATRIX, angle.f)
Declare D3DpbMatrixScaling(*out.D3DpbMATRIX, sx.f, sy.f, sz.f)
Declare D3DpbMatrixTranslation(*out.D3DpbMATRIX, x.f, y.f, z.f)


;
; ------------------------------------------------------------
;


; magnitude
Procedure.f D3DpbMagnitude(*v.D3DpbVECTOR3)
  ProcedureReturn Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
EndProcedure

; normalize
Procedure D3DpbNormalize(*v.D3DpbVECTOR3)
  len.f = D3DpbMagnitude(*v)
  *v\x / len : *v\y / len : *v\z / len
EndProcedure

; dotproduct
Procedure.f D3DpbDot(*v1.D3DpbVECTOR3, *v2.D3DpbVECTOR3) 
  ProcedureReturn *v1\x * *v2\x + *v1\y * *v2\y + *v1\z * *v2\z 
EndProcedure 

; crossproduct
Procedure D3DpbCross(*out.D3DpbVECTOR3, *v1.D3DpbVECTOR3, *v2.D3DpbVECTOR3)
  *out\x = (*v1\y * *v2\z) - (*v1\z * *v2\y)
  *out\y = (*v1\z * *v2\x) - (*v1\x * *v2\z)
  *out\z = (*v1\x * *v2\y) - (*v1\y * *v2\x)
EndProcedure

; subtraction
Procedure D3DpbSubstract(*out.D3DpbVECTOR3, *a.D3DpbVECTOR3, *b.D3DpbVECTOR3)
  *out\x = *a\x - *b\x
  *out\y = *a\y - *b\y
  *out\z = *a\z - *b\z
EndProcedure

;
; ------------------------------------------------------------
;

;
; Builds a left-handed perspective projection matrix
;
Procedure D3DpbMatrixLookAtLH(*out.D3DpbMATRIX, *eye.D3DpbVECTOR3, *at.D3DpbVECTOR3, *up.D3DpbVECTOR3)
  ; zaxis = normal(At - Eye)  
  D3DpbSubstract(zaxis.D3DpbVECTOR3, *at, *eye)
  D3DpbNormalize(zaxis.D3DpbVECTOR3)

  ; xaxis = normal(cross(Up, zaxis))  
  D3DpbCross(xaxis.D3DpbVECTOR3, *up, zaxis)
  D3DpbNormalize(xaxis)

  ; yaxis = cross(zaxis, xaxis)  
  D3DpbCross(yaxis.D3DpbVECTOR3, zaxis, xaxis)
  
  xdot.f = D3DpbDot(xaxis, *eye)
  ydot.f = D3DpbDot(yaxis, *eye)
  zdot.f = D3DpbDot(zaxis, *eye)  
  
  *out\_11 = xaxis\x : *out\_12 = yaxis\x : *out\_13 = zaxis\x : *out\_14 = 0.0
  *out\_21 = xaxis\y : *out\_22 = yaxis\y : *out\_23 = zaxis\y : *out\_24 = 0.0
  *out\_31 = xaxis\z : *out\_32 = yaxis\z : *out\_33 = zaxis\z : *out\_34 = 0.0
  *out\_41 = -xdot   : *out\_42 = -ydot   : *out\_43 = -zdot   : *out\_44 = 1.0
EndProcedure

;
; Builds a left-handed orthogonal projection matrix.
;
Procedure D3DpbMatrixOrthoLH(*out.D3DpbMATRIX, w.f, h.f, zn.f, zf.f)
  *out\_11 = 2/w  : *out\_12 = 0.0  : *out\_13 = 0.0        : *out\_14 = 0.0
  *out\_21 = 0.0  : *out\_22 = 2/h  : *out\_23 = 0.0        : *out\_24 = 0.0
  *out\_31 = 0.0  : *out\_32 = 0.0  : *out\_33 = 1/(zf-zn)  : *out\_34 = 0.0
  *out\_41 = 0.0  : *out\_42 = 0.0  : *out\_43 = zn/(zn-zf) : *out\_44 = 1.0
EndProcedure

;
; Builds a left-handed perspective projection matrix based on a field of view (FOV).
;
Procedure D3DpbMatrixPerspectiveFovLH(*out.D3DpbMATRIX, fov.f, aspect.f, zn.f, zf.f)
  h.f = Cos(fov/2) / Sin(fov/2)
  w.f= h / aspect

  *out\_11 = 2*zn/w : *out\_12 = 0.0    : *out\_13 = 0.0            : *out\_14 = 0.0
  *out\_21 = 0.0    : *out\_22 = 2*zn/h : *out\_23 = 0.0            : *out\_24 = 0.0
  *out\_31 = 0.0    : *out\_32 = 0.0    : *out\_33 = zf/(zf-zn)     : *out\_34 = 1.0
  *out\_41 = 0.0    : *out\_42 = 0.0    : *out\_43 = zn*zf/(zn-zf)  : *out\_44 = 0.0
EndProcedure

;
; Builds a left-handed perspective projection matrix
;
Procedure D3DpbMatrixPerspectiveLH(*out.D3DpbMATRIX, w.f, h.f, zn.f, zf.f)
  *out\_11 = 2*zn/w : *out\_12 = 0.0    : *out\_13 = 0.0            : *out\_14 = 0.0
  *out\_21 = 0.0    : *out\_22 = 2*zn/h : *out\_23 = 0.0            : *out\_24 = 0.0
  *out\_31 = 0.0    : *out\_32 = 0.0    : *out\_33 = zf/(zf-zn)     : *out\_34 = 1.0
  *out\_41 = 0.0    : *out\_42 = 0.0    : *out\_43 = zn*zf/(zn-zf)  : *out\_44 = 0.0
EndProcedure

;
; Builds a matrix that rotates around the x-axis.
;
Procedure D3DpbMatrixRotationX(*out.D3DpbMATRIX, angle.f)
   tsin.f = Sin(angle)
   tcos.f = Cos(angle)

  *out\_11 = 1.0  : *out\_12 = 0.0    : *out\_13 = 0.0  : *out\_14 = 0.0
  *out\_21 = 0.0  : *out\_22 =  tcos  : *out\_23 = tsin : *out\_24 = 0.0
  *out\_31 = 0.0  : *out\_32 = -tsin  : *out\_33 = tcos : *out\_34 = 0.0
  *out\_41 = 0.0  : *out\_42 = 0.0    : *out\_43 = 0.0  : *out\_44 = 1.0
EndProcedure

;
; Builds a matrix that rotates around the Y-axis.
;
Procedure D3DpbMatrixRotationY(*out.D3DpbMATRIX, angle.f)
   tsin.f = Sin(angle)
   tcos.f = Cos(angle)

  *out\_11 = tcos : *out\_12 = 0.0  : *out\_13 = -tsin  : *out\_14 = 0.0
  *out\_21 = 0.0  : *out\_22 = 1.0  : *out\_23 =  0.0   : *out\_24 = 0.0
  *out\_31 = tsin : *out\_32 = 0.0  : *out\_33 =  tcos  : *out\_34 = 0.0
  *out\_41 = 0.0  : *out\_42 = 0.0  : *out\_43 =  0.0   : *out\_44 = 1.0
EndProcedure

;
; Builds a matrix that rotates around the Z-axis.
;
Procedure D3DpbMatrixRotationZ(*out.D3DpbMATRIX, angle.f)
   tsin.f = Sin(angle)
   tcos.f = Cos(angle)

  *out\_11 =  tcos  : *out\_12 = tsin : *out\_13 = 0.0  : *out\_14 = 0.0
  *out\_21 = -tsin  : *out\_22 = tcos : *out\_23 = 0.0  : *out\_24 = 0.0
  *out\_31 =  0.0   : *out\_32 = 0.0  : *out\_33 = 1.0  : *out\_34 = 0.0
  *out\_41 =  0.0   : *out\_42 = 0.0  : *out\_43 = 0.0  : *out\_44 = 1.0
EndProcedure

;
; Builds a matrix that scales along the x-, y-, and z-axes.
;
Procedure D3DpbMatrixScaling(*out.D3DpbMATRIX, sx.f, sy.f, sz.f)
  *out\_11 = sx   : *out\_12 = 0.0 : *out\_13 = 0.0 : *out\_14 = 0.0
  *out\_21 = 0.0  : *out\_22 = sy  : *out\_23 = 0.0 : *out\_24 = 0.0
  *out\_31 = 0.0  : *out\_32 = 0.0 : *out\_33 = sz  : *out\_34 = 0.0
  *out\_41 = 0.0  : *out\_42 = 0.0 : *out\_43 = 0.0 : *out\_44 = 1.0
EndProcedure

;
; Builds a matrix using the specified offsets.
;
Procedure D3DpbMatrixTranslation(*out.D3DpbMATRIX, x.f, y.f, z.f)
  *out\_11 = 1.0 : *out\_12 = 0.0 : *out\_13 = 0.0  : *out\_14 = 0.0
  *out\_21 = 0.0 : *out\_22 = 1.0 : *out\_23 = 0.0  : *out\_24 = 0.0
  *out\_31 = 0.0 : *out\_32 = 0.0 : *out\_33 = 1.0  : *out\_34 = 0.0
  *out\_41 = x   : *out\_42 = y   : *out\_43 = z    : *out\_44 = 1.0
EndProcedure
EDIT:

Sorry, I made a stupid mistake at D3DpbMatrixOrthoLH(), it's
*out\_33 = 1/(zf-zn) and not *out\_33 = 1/(zf-zf) of course. :oops:

Corrected.
Last edited by traumatic on Thu Nov 04, 2004 5:40 pm, edited 2 times in total.
Good programmers don't comment their code. It was hard to write, should be hard to read.
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Re: D3DX Replacement Functions

Post by traumatic »

There were two indispensable functions missing, MatrixIdentity() and MatrixMultiply().

Well, here they go:

Code: Select all

;
; Determines the product of two matrices.
;
Procedure D3DpbMatrixMultiply(*out.D3DpbMATRIX, *m1.D3DpbMATRIX, *m2.D3DpbMATRIX)
   *out\_11 = *m1\_11 * *m2\_11 + *m1\_12 * *m2\_21 + *m1\_13 * *m2\_31 + *m1\_14 * *m2\_41
   *out\_12 = *m1\_11 * *m2\_12 + *m1\_12 * *m2\_22 + *m1\_13 * *m2\_32 + *m1\_14 * *m2\_42
   *out\_13 = *m1\_11 * *m2\_13 + *m1\_12 * *m2\_23 + *m1\_13 * *m2\_33 + *m1\_14 * *m2\_43
   *out\_14 = *m1\_11 * *m2\_14 + *m1\_12 * *m2\_24 + *m1\_13 * *m2\_34 + *m1\_14 * *m2\_44
                                                                         
   *out\_21 = *m1\_21 * *m2\_11 + *m1\_22 * *m2\_21 + *m1\_23 * *m2\_31 + *m1\_24 * *m2\_41
   *out\_22 = *m1\_21 * *m2\_12 + *m1\_22 * *m2\_22 + *m1\_23 * *m2\_32 + *m1\_24 * *m2\_42
   *out\_23 = *m1\_21 * *m2\_13 + *m1\_22 * *m2\_23 + *m1\_23 * *m2\_33 + *m1\_24 * *m2\_43
   *out\_24 = *m1\_21 * *m2\_14 + *m1\_22 * *m2\_24 + *m1\_23 * *m2\_34 + *m1\_24 * *m2\_44
                                                                         
   *out\_31 = *m1\_31 * *m2\_11 + *m1\_32 * *m2\_21 + *m1\_33 * *m2\_31 + *m1\_34 * *m2\_41
   *out\_32 = *m1\_31 * *m2\_12 + *m1\_32 * *m2\_22 + *m1\_33 * *m2\_32 + *m1\_34 * *m2\_42
   *out\_33 = *m1\_31 * *m2\_13 + *m1\_32 * *m2\_23 + *m1\_33 * *m2\_33 + *m1\_34 * *m2\_43
   *out\_34 = *m1\_31 * *m2\_14 + *m1\_32 * *m2\_24 + *m1\_33 * *m2\_34 + *m1\_34 * *m2\_44
                                                                         
   *out\_41 = *m1\_41 * *m2\_11 + *m1\_42 * *m2\_21 + *m1\_43 * *m2\_31 + *m1\_44 * *m2\_41
   *out\_42 = *m1\_41 * *m2\_12 + *m1\_42 * *m2\_22 + *m1\_43 * *m2\_32 + *m1\_44 * *m2\_42
   *out\_43 = *m1\_41 * *m2\_13 + *m1\_42 * *m2\_23 + *m1\_43 * *m2\_33 + *m1\_44 * *m2\_43
   *out\_44 = *m1\_41 * *m2\_14 + *m1\_42 * *m2\_24 + *m1\_43 * *m2\_34 + *m1\_44 * *m2\_44
EndProcedure

;
; Creates an identity matrix.
;
Procedure D3DpbMatrixIdentity(*out.D3DpbMATRIX)
  *out\_11 = 1.0 : *out\_12 = 0.0 : *out\_13 = 0.0  : *out\_14 = 0.0
  *out\_21 = 0.0 : *out\_22 = 1.0 : *out\_23 = 0.0  : *out\_24 = 0.0
  *out\_31 = 0.0 : *out\_32 = 0.0 : *out\_33 = 1.0  : *out\_34 = 0.0
  *out\_41 = 0.0 : *out\_42 = 0.0 : *out\_43 = 0.0  : *out\_44 = 1.0
EndProcedure

BTW, does anyone actually use this stuff?
Good programmers don't comment their code. It was hard to write, should be hard to read.
dige
Addict
Addict
Posts: 1413
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post by dige »

Could you provide an working example for that?

cya dige
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

Just use the procedures in exactly the same way as the original D3DX ones.



From the dx8-sdk :
(/samples/Multimedia/Direct3D/Tutorials/Tut03_Matrices/ )

Code: Select all

;-----------------------------------------------------------------------------
; Name: SetupMatrices()
; Desc: Sets up the world, view, and projection transform matrices.
;-----------------------------------------------------------------------------
Procedure SetupMatrices()
    Shared d3dDevice.IDirect3DDevice8
    ; For our world matrix, we will just rotate the object about the y-axis.
    matWorld.D3DpbMATRIX
    D3DpbMatrixRotationY( @matWorld, timeGetTime_()/150.0 )
    d3dDevice\SetTransform( #D3DTS_WORLD, @matWorld )

    ; Set up our view matrix. A view matrix can be defined given an eye point,
    ; a point to lookat, and a direction for which way is up. Here, we set the
    ; eye five units back along the z-axis and up three units, look at the
    ; origin, and define "up" to be in the y-direction.
    matView.D3DpbMATRIX
    eye.D3DpbVECTOR3 : at.D3DpbVECTOR3 : up.D3DpbVECTOR3
    eye\y = 3.0 : eye\z = -5.0 : up\y = 1.0
    
    D3DpbMatrixLookAtLH( @matView, eye, at, up );
    d3dDevice\SetTransform( #D3DTS_VIEW, @matView );

    ; For the projection matrix, we set up a perspective transform (which
    ; transforms geometry from 3D view space to 2D viewport space, with
    ; a perspective divide making objects smaller in the distance). To build
    ; a perpsective transform, we need the field of view (1/4 pi is common),
    ; the aspect ratio, and the near and far clipping planes (which define at
    ; what distances geometry should be no longer be rendered).
    matProj.D3DpbMATRIX
    D3DpbMatrixPerspectiveFovLH( @matProj, #D3DX_PI/4, 1.0, 1.0, 100.0 )
    d3dDevice\SetTransform( #D3DTS_PROJECTION, @matProj )
EndProcedure

Got the idea?
Good programmers don't comment their code. It was hard to write, should be hard to read.
Post Reply