Qbasicnews.com

Full Version: Matrix math... easier?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hey, I'm studying flipcode's demomaking tutorials now, and I wanted to see if I could port the particle program into QB.

I got pretty far in, but I realized my matrix math was all wrong. I relearned the formulas, and now I'm thinking... is this all feasible in QB?

What it does is rotate a 3x3 matrix, multiply that by another rotated matrix, multiplied by yet another rotated matrix, and then multiplies by a vector.

After all that, it has to do a whole bunch of other stuff too.
If you wanna see the code, it's at the end of the tutorial here: http://www.flipcode.com/demomaking/issue11.shtml

I..... didn't read the tutorial Tongue

Anyways, one more problem I had was with the buffers. It uses two buffers in that tutorials, and... using two buffers means a LOT of DEF SEGs. Anyone with a bit of time think they can help me with this?

::EDIT::
Ok, I guess I'll let you see my code. Keep in mind the matrix multiplying is wrong, but the rotations are right. I even commented where I threw my temper tantrum Tongue

Code:
DEFINT A-Z
'$DYNAMIC
TYPE VECTOR
v1 AS SINGLE
v2 AS SINGLE
v3 AS SINGLE
END TYPE
DECLARE FUNCTION MatRotX(DOUBLE theta)
DECLARE FUNCTION MatRotY(DOUBLE theta)
DECLARE FUNCTION MatRotZ(DOUBLE theta)
DECLARE SUB Rescale(src() AS STRING*1, dst() AS STRING*1)
DECLARE SUB Blur(src() AS STRING*1, dst() AS STRING*1)
DECLARE SUB Draw(where() AS STRING * 1, v AS VECTOR)
DECLARE SUB ptsFill(i),mm1 AS DOUBLE,mm2 AS DOUBLE,mm3 AS DOUBLE

CONST MaxPoints = 4096
CONST PI=3.141592654#
CONST PI2=6.283185307#
CONST PI256=PI/256
DIM SHARED base_dist AS SINGLE, scaleX(320), scaleY(200)
DIM SHARED page1(64000) AS STRING * 1
DIM SHARED page2(64000) AS STRING * 1
DIM SHARED points(MAXPOINTS-1) as VECTOR

DIM mat1(2,2), mat2(2,2), mat3(2,2),t1 AS VECTOR
DIM cos1 AS DOUBLE,cos2 AS DOUBLE, cos3 AS DOUBLE
DIM c1 AS DOUBLE, c2 AS DOUBLE, c3 AS DOUBLE
DIM s1 AS DOUBLE, s2 AS DOUBLE, s3 AS DOUBLE

FOR i=0 to 255
OUT &H3C8, i
OUT &H3C9, i\4
OUT &H3C9, i\4
OUT &H3C9, i\4
NEXT

FOR i=0 to MAXPOINTS-1
  ptsFill(i)
  points.v1=mm1:points.v2=mm2:points.v3=mm3
next
DO
curTime=TIMER/16384
iPI=i*PI256
r=32+31*cos(iPI+curTime/74)
g=32+31*cos(iPI+curTime/63)
b=32+31*cos(iPI+curTime/81)

FOR i=0 to 127
i128=i/128
OUT &H3C8,i
OUT &H3C9,r*i128
OUT &H3C9,g*i128
OUT &H3C9,b*i128

OUT &H3C8,128+i
OUT &H3C9,(63-r)*i128
OUT &H3C9,(63-g)*i128
OUT &H3C9,(63-b)*i128
NEXT

sx=INT(160-80*sin(curTime/559))
sy=INT(100+50*sin(curTime/611))
for i=0 to 319
scaleX(i)=INT(sx+(i-sX)*.85)
NEXT
FOR i=0 to 199
scaleY(i)=INT(sy+(i-sy)*.85)
NEXT
Rescale (page2,page1)
Blur (page1,page2)

base_dist = 256+64*sin(curTime/327)

'rotate X
cos1=PI2*sin(curTime/289)
c1=cos(cos1)
s1=sin(cos1)
mat1(0,0)=1:mat1(1,0)=0:mat1(2,0)=0
mat1(0,1)=0:mat1(1,1)=c1:mat1(2,1)=s1
mat1(0,2)=0:mat1(1,2)=-s1:mat1(2,2)=c1

'rotate Y
cos2=PI2*cos(curTime/307)
c2=cos(cos2)
s2=sin(cos2)
mat2(0,0)=c2:mat2(1,0)=0:mat2(2,0)=-s2
mat2(0,1)=0:mat2(1,1)=1:mat2(2,1)=0
mat2(0,2)=s2:mat2(1,2)=0:mat2(2,2)=c2

'rotate Z
cos3=-PI2*sin(curTime/251)
c3=cos(cos3)
s3=sin(cos3)
mat3(0,0)=c3:mat3(1,0)=s3:mat3(2,0)=0
mat3(0,1)=-s2:mat3(1,1)=c3:mat3(2,1)=0
mat3(0,2)=0:mat3(1,2)=0:mat3(2,2)=1
'mult X by Y
mat1(0,0)=mat1(0,0)*mat2(0,0)
mat1(1,0)=mat1(1,0)*mat2(0,1)
mat1(2,0)=mat1(2,0)*mat2(0,2) 'now to row 2
mat1(0,1)=mat1(0,1)*mat2(1,0)
mat1(1,1)=mat1(1,1)*mat2(1,1)
mat1(2,1)=mat1(2,1)*mat2(1,2) 'now to row 3
mat1(0,2)=mat1(0,2)*mat2(2,0)
mat1(1,2)=mat1(1,2)*mat2(2,1)
mat1(2,2)=mat1(2,2)*mat2(2,2)
'mult XY by Z
mat1(0,0)=mat1(0,0)*mat3(0,0)
mat1(1,0)=mat1(1,0)*mat3(0,1)
mat1(2,0)=mat1(2,0)*mat3(0,2) 'now to row 2
mat1(0,1)=mat1(0,1)*mat3(1,0)
mat1(1,1)=mat1(1,1)*mat3(1,1)
mat1(2,1)=mat1(2,1)*mat3(1,2) 'now to row 3
mat1(0,2)=mat1(0,2)*mat3(2,0)
mat1(1,2)=mat1(1,2)*mat3(2,1)
mat1(2,2)=mat1(2,2)*mat3(2,2)

FOR i=0 to MaxPoints-1
t1.v1=mat1(
'CRAAAAAAAAAAAAAAAAAAAAAAAP!!!!!!!!!!!!!!!!!!!
'This is where I realized I messed up. Pretty dumb, eh?

'multiply by vector
v1#=64+16*sin(i/191)
mm1=mat1(0,0)*v1#
mm2=mat1(0,1)*v1#
mm3=mat1(0,2)*v1#

       for (i=0; i<MAXPTS; i++) Draw( page2, obj * pts[i] );
    // dump our temporary buffer to the screen
       vga->Update();
       frameCount++;

SUB Rescale(src() AS STRING*1, dst() AS STRING*1)
offs& = 0
for j=0 to 199
  for i=0 to 319
    dst(offs&) = src(scaleY(j)*320+scaleX(i))
    offs&=offs&+1
  next
next
END SUB

SUB Blur(src() AS STRING*1, dst() AS STRING*1)
offs&=320
FOR j=1 to 198
  dst(offs&)=0:offs&=offs&+1
  FOR i= 1 to 318
    k = (VAL(src(offs&-321))+VAL(src(offs&-320))+VAL(src(offs&-319))+VAL(src(offs&-1))
    k=(k+VAL(src(offs&+1))+VAL(src(offs&+319))+VAL(src(offs&+320))+VAL(src(offs&+321)))\8
    if k>16 then k=k-16 else k=0
    dst(offs&)=CHR$(k)
    offs&=offs&+1
  NEXT
  dst(offs&)=CHR$(0) offs&=offs&+1
NEXT
END SUB

SUB Draw(where() AS STRING * 1, v AS VECTOR)
DIM iz AS SINGLE,x AS SINGLE, y AS SINGLE
iz = 1/(v.v3+base_dist)
x = 160+160*v.v1*iz
y=100+160*v.2*iz

IF (x<0 OR x>319 OR y<0 OR y>199) THEN EXIT SUB
sx=INT(x*8)
sy=INT(y*8)
syOe=sy\8
offs&=syOe*320+syOe
sx = sx AND 7
sy = sy AND 7

c=VAL(where(offs&))
c=c+(7-sx)*(7-sy)
  IF c>255 THEN c=255
  where(offs&)=CHR$(c)
c=VAL(where(offs&+1))
c=c+(7-sy)*sx
  IF c>255 then c=255
  where(offs&+1)=CHR$(c)
c=VAL(where(offs&+320))
c=c+sy*(7-sx)
  IF c>255 then c=255
  where(offs&+320)=chr$(c)
c=VAL(where(offs&+321))
c=c+sy*sx
  IF c>255 then c=255
  where(offs&+321)=chr$(c)
END SUB

SUB ptsFill(i)
DIM mat1(2,2), mat2(2,2), mat3(2,2)
DIM cos1 AS DOUBLE,cos2 AS DOUBLE, cos3 AS DOUBLE
DIM c1 AS DOUBLE, c2 AS DOUBLE, c3 AS DOUBLE
DIM s1 AS DOUBLE, s2 AS DOUBLE, s3 AS DOUBLE

'rotate X
cos1=PI2*sin(i/203)
c1=cos(cos1)
s1=sin(cos1)
mat1(0,0)=1:mat1(1,0)=0:mat1(2,0)=0
mat1(0,1)=0:mat1(1,1)=c1:mat1(2,1)=s1
mat1(0,2)=0:mat1(1,2)=-s1:mat1(2,2)=c1

'rotate Y
cos2=PI2*cos(i/157)
c2=cos(cos2)
s2=sin(cos2)
mat2(0,0)=c2:mat2(1,0)=0:mat2(2,0)=-s2
mat2(0,1)=0:mat2(1,1)=1:mat2(2,1)=0
mat2(0,2)=s2:mat2(1,2)=0:mat2(2,2)=c2

'rotate Z
cos3=-PI2*cos(i/181)
c3=cos(cos3)
s3=sin(cos3)
mat3(0,0)=c3:mat3(1,0)=s3:mat3(2,0)=0
mat3(0,1)=-s2:mat3(1,1)=c3:mat3(2,1)=0
mat3(0,2)=0:mat3(1,2)=0:mat3(2,2)=1
'mult X by Y
mat1(0,0)=mat1(0,0)*mat2(0,0)
mat1(1,0)=mat1(1,0)*mat2(0,1)
mat1(2,0)=mat1(2,0)*mat2(0,2) 'now to row 2
mat1(0,1)=mat1(0,1)*mat2(1,0)
mat1(1,1)=mat1(1,1)*mat2(1,1)
mat1(2,1)=mat1(2,1)*mat2(1,2) 'now to row 3
mat1(0,2)=mat1(0,2)*mat2(2,0)
mat1(1,2)=mat1(1,2)*mat2(2,1)
mat1(2,2)=mat1(2,2)*mat2(2,2)
'mult XY by Z
mat1(0,0)=mat1(0,0)*mat3(0,0)
mat1(1,0)=mat1(1,0)*mat3(0,1)
mat1(2,0)=mat1(2,0)*mat3(0,2) 'now to row 2
mat1(0,1)=mat1(0,1)*mat3(1,0)
mat1(1,1)=mat1(1,1)*mat3(1,1)
mat1(2,1)=mat1(2,1)*mat3(1,2) 'now to row 3
mat1(0,2)=mat1(0,2)*mat3(2,0)
mat1(1,2)=mat1(1,2)*mat3(2,1)
mat1(2,2)=mat1(2,2)*mat3(2,2)

'multiply by vector
v1#=64+16*sin(i/191)
mm1=mat1(0,0)*v1#
mm2=mat1(0,1)*v1#
mm3=mat1(0,2)*v1#
END SUB
The computations themselves are the same with or without the matrix. Matrices really just provide a convenient symbolism to simplify mathemtatical analysis. Now, if you have someone else's subroutine to perform rotations or other "matrix transformations," and all you have to do is input the matrix elements to it, yes, that may make things easier for *you*. However, the guy who wrote the subroutine had to forget about the matrix and work with the fundamental math beneath it.
His code uses classes and operators, so I have to completely rewrite his code... it's just not that simple :\
Quote:His code uses classes and operators, so I have to completely rewrite his code... it's just not that simple :\

But matrices won't have a bearing on classes and operators. If you wan't you could use any 3d rotation formula and use the "standard" Expanding,distributing trick to get the final 3*3 matrix. I've done that. :*)