Author Topic: Matrix and Quaternion Hardcore  (Read 8282 times)

0 Members and 1 Guest are viewing this topic.

Charles Pegge

  • Guest
Matrix and Quaternion Hardcore
« on: April 12, 2015, 01:20:42 AM »
inc\glo2\glMath.inc

This file contains a collection of transform functions targeted for Opengl 3.3 where glPushMatrix and glPopMatrix, and many other functions are banished!

Code: OxygenBasic
  1.  
  2.   '================
  3.  'MATRIX MATHS ETC
  4.  '================
  5.  
  6.  
  7.  
  8.   string tab=chr(9)
  9.   string cr=chr(13,10)
  10.  
  11.   macro ShowBuffer(n)
  12.   ===================
  13.   string bu=space n
  14.   end macro
  15.  
  16.   macro ShowTitle(v)
  17.   ==================
  18.   mid bu,c,v cr : c+=2+len v
  19.   end macro
  20.  
  21.   macro ShowElement(v)
  22.   ====================
  23.   mid bu,c,"  "+str(v,4) : c+=14
  24.   end macro
  25.  
  26.   macro ShowNextLine()
  27.   ====================
  28.   mid bu,c,cr : c+=2
  29.   end macro
  30.  
  31.  
  32.   macro ShowReturn()
  33.   ==================
  34.   return left bu,c-1
  35.   end macro
  36.  
  37.  
  38.   function ShowVec(float *v, sys n=3) as string
  39.   =============================================
  40.   indexbase 0
  41.   ShowBuffer 256
  42.   sys c=1
  43.   n--
  44.   ShowTitle "Vector:"
  45.   for i=0 to n
  46.     ShowElement v[i]
  47.   next
  48.   ShowNextLine
  49.   ShowReturn
  50.   end function
  51.  
  52.  
  53.   function ShowMat(float*m,sys r=4) as string
  54.   ===========================================
  55.   indexbase 0
  56.   ShowBuffer 512
  57.   string s
  58.   sys c,e,i,j,k,n
  59.   static double min=1.0e-7
  60.   c=1
  61.   n=r-1
  62.   e=r*r-1
  63.   ShowTitle "Matrix:"
  64.   for i=0 to n 'column
  65.    for j=0 to e step r 'row
  66.      k=i+j
  67.       ShowElement m[k]
  68.     next
  69.     ShowNextLine
  70.   next
  71.   ShowReturn
  72.   end function
  73.  
  74.  
  75.   function Transpose(float *r, *m, int n=4)
  76.   =========================================
  77.   indexbase 0
  78.   sys i,j,k1,k2
  79.   sys e=n-1
  80.   for i=0 to e
  81.     k2=i
  82.     for j=0 to e
  83.       r[k1]=m[k2] : k1++ : k2+=n
  84.     next
  85.   next  
  86.   end function
  87.  
  88.  
  89.   function Identity(float *m, int n=4)
  90.   ====================================
  91.   indexbase 0
  92.   sys h=n+1, e=n*n-1
  93.   for i=0 to e
  94.     m[i]=0.0
  95.   next
  96.   for i=0 to e step h
  97.     m[i]=1.0
  98.   next
  99.   end function
  100.  
  101.  
  102.   function det2x2sub(float *m, int i0,i1,i2,i3) as float
  103.   ======================================================
  104.   indexbase 0
  105.   return m[i0] * m[i3] - m[i2] * m[i1]
  106.   end function
  107.  
  108.  
  109.   function InverseMat3x3(float *r, *m)
  110.   ====================================
  111.   indexbase 0
  112.   float det = 0.0f
  113.   '
  114.  det += m[0] * det2x2sub(m, 4, 5, 7, 8)
  115.   det -= m[3] * det2x2sub(m, 1, 2, 7, 8)
  116.   det += m[6] * det2x2sub(m, 1, 2, 4, 5)
  117.   '
  118.  r[0] =  det2x2sub(m, 4, 5, 7, 8) / det
  119.   r[1] = -det2x2sub(m, 1, 2, 7, 8) / det
  120.   r[2] =  det2x2sub(m, 1, 2, 4, 5) / det
  121.   r[3] = -det2x2sub(m, 3, 5, 6, 8) / det
  122.   r[4] =  det2x2sub(m, 0, 2, 6, 8) / det
  123.   r[5] = -det2x2sub(m, 0, 2, 3, 5) / det
  124.   r[6] =  det2x2sub(m, 3, 4, 6, 7) / det
  125.   r[7] = -det2x2sub(m, 0, 1, 6, 7) / det
  126.   r[8] =  det2x2sub(m, 0, 1, 3, 4) / det
  127.   end function
  128.  
  129.  
  130.   function Mat4x4ToMat3x3(float *r,*m)
  131.   ====================================
  132.   indexbase 0
  133.   'copy top left section
  134.  r[0] = m[0]
  135.   r[3] = m[4]
  136.   r[6] = m[8]
  137.   r[1] = m[1]
  138.   r[4] = m[5]
  139.   r[7] = m[9]
  140.   r[2] = m[2]
  141.   r[5] = m[6]
  142.   r[8] = m[10]
  143.   end function
  144.  
  145.  
  146.   function mat4x4Mul(float *r,*m1,*m2)
  147.   ====================================
  148.   indexbase 0
  149.   r[0]  = m1[0] * m2[0]  + m1[4] * m2[1]  + m1[8]  * m2[2]  + m1[12] * m2[3]
  150.   r[1]  = m1[1] * m2[0]  + m1[5] * m2[1]  + m1[9]  * m2[2]  + m1[13] * m2[3]
  151.   r[2]  = m1[2] * m2[0]  + m1[6] * m2[1]  + m1[10] * m2[2]  + m1[14] * m2[3]
  152.   r[3]  = m1[3] * m2[0]  + m1[7] * m2[1]  + m1[11] * m2[2]  + m1[15] * m2[3]
  153.   r[4]  = m1[0] * m2[4]  + m1[4] * m2[5]  + m1[8]  * m2[6]  + m1[12] * m2[7]
  154.   r[5]  = m1[1] * m2[4]  + m1[5] * m2[5]  + m1[9]  * m2[6]  + m1[13] * m2[7]
  155.   r[6]  = m1[2] * m2[4]  + m1[6] * m2[5]  + m1[10] * m2[6]  + m1[14] * m2[7]
  156.   r[7]  = m1[3] * m2[4]  + m1[7] * m2[5]  + m1[11] * m2[6]  + m1[15] * m2[7]
  157.   r[8]  = m1[0] * m2[8]  + m1[4] * m2[9]  + m1[8]  * m2[10] + m1[12] * m2[11]
  158.   r[9]  = m1[1] * m2[8]  + m1[5] * m2[9]  + m1[9]  * m2[10] + m1[13] * m2[11]
  159.   r[10] = m1[2] * m2[8]  + m1[6] * m2[9]  + m1[10] * m2[10] + m1[14] * m2[11]
  160.   r[11] = m1[3] * m2[8]  + m1[7] * m2[9]  + m1[11] * m2[10] + m1[15] * m2[11]
  161.   r[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8]  * m2[14] + m1[12] * m2[15]
  162.   r[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9]  * m2[14] + m1[13] * m2[15]
  163.   r[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15]
  164.   r[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15]
  165.   end function
  166.  
  167.  
  168.   function transformVec4(float *r,*m,*v, sys n=0)
  169.   ===============================================
  170.   'using mat4x4
  171.  indexbase 0
  172.   sys i
  173.   for i=0 to n
  174.     r[0]  = m[0] * v[0]  + m[4] * v[1]  + m[8]  * v[2]  + m[12] * v[3]
  175.     r[1]  = m[1] * v[0]  + m[5] * v[1]  + m[9]  * v[2]  + m[13] * v[3]
  176.     r[2]  = m[2] * v[0]  + m[6] * v[1]  + m[10] * v[2]  + m[14] * v[3]
  177.     r[3]  = m[3] * v[0]  + m[7] * v[1]  + m[11] * v[2]  + m[15] * v[3]
  178.     @v+=16
  179.     @r+=16
  180.   next
  181.   end function
  182.  
  183.  
  184.   function transformVec3(float *r,*m,*v, sys n=1)
  185.   ===============================================
  186.   'using mat4x4
  187.  indexbase 0
  188.   sys i
  189.   n--
  190.   for i=0 to n
  191.     r[0]  = m[0] * v[0]  + m[4] * v[1]  + m[8]  * v[2]  + m[12]
  192.     r[1]  = m[1] * v[0]  + m[5] * v[1]  + m[9]  * v[2]  + m[13]
  193.     r[2]  = m[2] * v[0]  + m[6] * v[1]  + m[10] * v[2]  + m[14]
  194.     @v+=12
  195.     @r+=12
  196.   next
  197.   end function
  198.  
  199.   macro rotsetup
  200.   ==============
  201.   indexbase 0
  202.   float m[16]
  203.   a = rad(a)
  204.   float ca = cos(a), sa = sin(a)
  205.   end macro
  206.  
  207.   function mat4x4rotateVecX(float *r, *v, a)
  208.   ==========================================
  209.   '
  210.  ' 1  0  0  0
  211.  ' 0  c -s  0
  212.  ' 0  s  c  0
  213.  ' 0  0  0  0
  214.  '
  215.  rotsetup
  216.   m[0]  = 1
  217.  'm[1]  = 0
  218. 'm[2]  = 0
  219. 'm[3]  = 0
  220.  ----------
  221.  'm[4]  = 0
  222.  m[5]  = ca
  223.   m[6]  = sa
  224.  'm[7]  = 0
  225.  ----------
  226.  'm[8]  = 0
  227.  m[9]  = -sa
  228.   m[10] = ca
  229.  'm[11] = 0
  230.  transformVec3 r,m,v
  231.   end function
  232.  
  233.  
  234.   function mat4x4rotateVecY(float *r, *v, a)
  235.   ==========================================
  236.   '
  237.  ' c  s  0  0
  238.  ' 0  1  0  0
  239.  '-s  0  c  0
  240.  ' 0  0  0  0
  241.  '
  242.  rotsetup
  243.   m[0]  = ca
  244.  'm[1]  = 0
  245.  m[2]  = -sa
  246.  'm[3]  = 0
  247.  ----------
  248.  'm[4]  = 0
  249.  m[5]  = 1
  250.  'm[6]  = 0
  251. 'm[7]  = 0
  252.  ----------
  253.   m[8]  = sa
  254.  'm[9]  = 0
  255.  m[10] = ca
  256.  'm[11] = 0
  257.  transformVec3 r,m,v
  258.   end function
  259.  
  260.  
  261.   function mat4x4rotateVecZ(float *r, *v, a)
  262.   ==========================================
  263.   '
  264.  ' c -s  0  0
  265.  ' s  c  0  0
  266.  ' 0  0  1  0
  267.  ' 0  0  0  0
  268.  '
  269.  rotsetup
  270.   m[0]  = ca
  271.   m[1]  = sa
  272.  'm[2]  = 0
  273. 'm[3]  = 0
  274.  ----------
  275.   m[4]  = -sa
  276.   m[5]  = ca
  277.  'm[6]  = 0
  278. 'm[7]  = 0
  279.  ----------
  280.  'm[8]  = 0
  281. 'm[9]  = 0
  282.  m[10] = 1
  283.  'm[11] = 0
  284.  transformVec3 r,m,v
  285.   end function
  286.  
  287.  
  288.   function det3x3sub(float *m, int i0,i1,i2,i3,i4,i5,i6,i7,i8) as float
  289.   =====================================================================
  290.   indexbase 0
  291.   float det
  292.   det += m[i0] * det2x2sub(m, i4, i5, i7, i8)
  293.   det -= m[i3] * det2x2sub(m, i1, i2, i7, i8)
  294.   det += m[i6] * det2x2sub(m, i1, i2, i4, i5)
  295.   return det;
  296.   end function
  297.  
  298.  
  299.   function mat4x4Inverse(float *r,*m)
  300.   ===================================
  301.   indexbase 0
  302.   float det
  303.   det += m[0]  * det3x3sub(m, 5, 6, 7, 9, 10, 11, 13, 14, 15)
  304.   det -= m[4]  * det3x3sub(m, 1, 2, 3, 9, 10, 11, 13, 14, 15)
  305.   det += m[8]  * det3x3sub(m, 1, 2, 3, 5,  6,  7, 13, 14, 15)
  306.   det -= m[12] * det3x3sub(m, 1, 2, 3, 5,  6,  7,  9, 10, 11)
  307.  
  308.   r[0]  =  det3x3sub(m, 5, 6, 7, 9, 10, 11, 13, 14, 15) / det;
  309.   r[1]  = -det3x3sub(m, 1, 2, 3, 9, 10, 11, 13, 14, 15) / det;
  310.   r[2]  =  det3x3sub(m, 1, 2, 3, 5,  6,  7, 13, 14, 15) / det;
  311.   r[3]  = -det3x3sub(m, 1, 2, 3, 5,  6,  7,  9, 10, 11) / det;
  312.   r[4]  = -det3x3sub(m, 4, 6, 7, 8, 10, 11, 12, 14, 15) / det;
  313.   r[5]  =  det3x3sub(m, 0, 2, 3, 8, 10, 11, 12, 14, 15) / det;
  314.   r[6]  = -det3x3sub(m, 0, 2, 3, 4,  6,  7, 12, 14, 15) / det;
  315.   r[7]  =  det3x3sub(m, 0, 2, 3, 4,  6,  7,  8, 10, 11) / det;
  316.   r[8]  =  det3x3sub(m, 4, 5, 7, 8,  9, 11, 12, 13, 15) / det;
  317.   r[9]  = -det3x3sub(m, 0, 1, 3, 8,  9, 11, 12, 13, 15) / det;
  318.   r[10] =  det3x3sub(m, 0, 1, 3, 4,  5,  7, 12, 13, 15) / det;
  319.   r[11] = -det3x3sub(m, 0, 1, 3, 4,  5,  7,  8,  9, 11) / det;
  320.   r[12] = -det3x3sub(m, 4, 5, 6, 8,  9, 10, 12, 13, 14) / det;
  321.   r[13] =  det3x3sub(m, 0, 1, 2, 8,  9, 10, 12, 13, 14) / det;
  322.   r[14] = -det3x3sub(m, 0, 1, 2, 4,  5,  6, 12, 13, 14) / det;
  323.   r[15] =  det3x3sub(m, 0, 1, 2, 4,  5,  6,  8,  9, 10) / det;
  324.   end function
  325.  
  326.  
  327.   function mat4x4scale(float *r, x, y, z)
  328.   =======================================
  329.   indexbase 0
  330.   r[0]  = x
  331.   r[5]  = y
  332.   r[10] = z
  333.   r[15] = 1
  334.   end function
  335.  
  336.  
  337.   function mat4x4Translate(float *r, x, y, z)
  338.   ===========================================
  339.   indexbase 0
  340.   r[12] = x
  341.   r[13] = y
  342.   r[14] = z
  343.   r[0]  = 1
  344.   r[5]  = 1
  345.   r[10] = 1
  346.   r[15] = 1
  347.   end function
  348.  
  349.  
  350.   function mat4x4rotate(float *r, a, x, y, z)
  351.   ===========================================
  352.   indexbase 0
  353.   a = rad(a)
  354.   double f=1/sqr(x*x+y*y+z*z)
  355.   x*=f : y*=f : z*=f 'normalise
  356.  float ca = 1.0 - cos(a), sa = sin(a)
  357.   r[0] = 1.0 + ca * (x * x - 1.0)
  358.   r[1] = ca * x * y + z * sa
  359.   r[2] = ca * x * z - y * sa
  360.   r[4] = ca * x * y - z * sa
  361.   r[5] = 1.0 + ca * (y * y - 1.0)
  362.   r[6] = ca * y * z + x * sa
  363.   r[8] = ca * x * z + y * sa
  364.   r[9] = ca * y * z - x * sa
  365.   r[10] = 1.0 + ca * (z * z - 1.0)
  366.   r[15] = 1.0
  367.   end function
  368.  
  369.  
  370.   type vec3 float x,y,z
  371.   =====================
  372.  
  373.   function Normalize(vec3 *r,*v)
  374.   ==============================
  375.   double f=1/sqr(v.x*v.x+v.y*v.y+v.z*v.z)
  376.   r.x=v.x*f
  377.   r.y=v.y*f
  378.   r.z=v.z*f
  379.   end function
  380.  
  381.  
  382.   function dot(vec3 *u,*v) as float
  383.   =================================
  384.   return u.x * v.x + u.y * v.y + u.z * v.z
  385.   end function
  386.  
  387.  
  388.   function cross(vec3 *r,*u,*v)
  389.   =============================
  390.   r.x = u.y * v.z - u.z * v.y
  391.   r.y = u.z * v.x - u.x * v.z
  392.   r.z = u.x * v.y - u.y * v.x
  393.   end function
  394.  
  395.  
  396.   function diff(vec3 *r,*u,*v)
  397.   ============================
  398.   r.x=u.x - v.x
  399.   r.y=u.y - v.y
  400.   r.z=u.z - v.z
  401.   end function
  402.  
  403.   function mat4x4Look(float *r, vec3 *eye,*center,*up)
  404.   ====================================================
  405.   indexbase 0
  406.   vec3 vx,vy,vz,vt
  407.   diff(eye,center,vt)
  408.   normalize(vt,vz)
  409.   '
  410.  cross(up,vz,vt)
  411.   normalize(vt,vx)
  412.   '
  413.  cross(vz,vx,vy)
  414.   '
  415.  r[0]  = vx.x
  416.   r[1]  = vy.x
  417.   r[2]  = vz.x
  418.   r[4]  = vx.y
  419.   r[5]  = vy.y
  420.   r[6]  = vz.y
  421.   r[8]  = vx.z
  422.   r[9]  = vy.z
  423.   r[10] = vz.z
  424.   r[12] = -dot(vx, eye)
  425.   r[13] = -dot(vy, eye)
  426.   r[14] = -dot(vz, eye)
  427.   end function
  428.  
  429.  
  430.   function CopyFloat(float *r,*s, int n=1)
  431.   ========================================
  432.   indexbase 0
  433.   sys i
  434.   n--
  435.   for i=0 to n
  436.     r[i] = s[i]
  437.   next
  438.   end function
  439.  
  440.  
  441.   function CopyVec(float *r,*s, int n=1)
  442.   ======================================
  443.   indexbase 0
  444.   sys i
  445.   n*=3
  446.   n--
  447.   for i=0 to n
  448.     r[i] = s[i]
  449.   next
  450.   end function
  451.  
  452.  
  453.   function CopyMat(float *r,*s, int n=1)
  454.   ======================================
  455.   indexbase 0
  456.   sys i
  457.   n*=16
  458.   n--
  459.   for i=0 to n
  460.     r[i] = s[i]
  461.   next
  462.   end function
  463.  
  464.  
  465.   '
  466.  'CAMERA SPACE
  467.  'http://ogldev.atspace.co.uk/www/tutorial13/tutorial13.html
  468.  '
  469.  function SetViewMatrix(float *r, vec3 *vp,*vu,*vv,*vn)
  470.   ======================================================
  471.   indexbase 0
  472.   vec3  u,v,n
  473.   float p[16], m[16]
  474.   '
  475.  identity p,4
  476.   p[12]={-vp.x, -vp.y, -vp.z}
  477.   '
  478.  normalize u,vu
  479.   normalize v,vv
  480.   normalize n,vn
  481.   'itr cross product u from n and v
  482.  '
  483.  '      U    V      N
  484.  '      UP   RIGHT  LOOKAT
  485.  --------------------------------------
  486.   m[0] = {u.x, v.x,  n.x, 0.0} 'column 0
  487.  m[4] = {u.y, v.y,  n.y, 0.0} 'column 1
  488.  m[8] = {u.z, v.z,  n.z, 0.0} 'column 2
  489.  m[12]= {0.0, 0.0,  0.0, 1.0} 'column 3
  490.  --------------------------------------
  491.   '
  492.  Mat4x4Mul r,m,p
  493.   '
  494.  end function
  495.  
  496.  
  497.  
  498.   'http://stackoverflow.com/questions/18404890/how-to-build-perspective-projection-matrix-no-api
  499.  'http://gamedev.stackexchange.com/questions/56609/how-to-create-a-projection-matrix-in-opengl-es-2-0
  500.  '**
  501.  'http://www.songho.ca/opengl/gl_projectionmatrix.html
  502.  'http://www.terathon.com/gdc07_lengyel.pdf
  503.  '
  504.  'http://www.swiftless.com/tutorials/opengl4/3-opengl-4-matrices.html
  505.  '
  506.  function SetProjectionMatrix(float *r, fov, aspect, near, far, int orth=0, leftHanded=1)
  507.   ========================================================================================
  508.   'FOV RECEIVED IN DEGREES
  509.  'ASPECT == VIEWPORT WIDTH/HEIGHT
  510.  '
  511.  indexbase 0
  512.   identity r,4
  513.   float h = 1 : if not lefthanded then h=-1
  514.   float i = 1 / (far-near)
  515.   float f = 1 / tan(rad(fov/2))
  516.   '
  517.  r[5] = aspect * f 'uh
  518.  r[0] = h * f      'uw
  519.  '
  520.  if orth then
  521.   '
  522.  'ORTHOGRAPHIC PROJECTION
  523.  -------------------------------------------------
  524.   '  uw        0         0            0
  525.  '  0         uh        0            0
  526.  '  0         0         -2/(f-n)     -(f+n)/(f-n)
  527.  '  0         0         0            1
  528.  -------------------------------------------------
  529.   '
  530.  r[10] = -2.0 * i
  531.   r[11] = 0
  532.   r[14] = -(far+near) * i
  533.   r[15] = 1
  534.   exit function
  535.   end if
  536.   '
  537.  'PERSPECTIVE PROJECTION
  538.  -------------------------------------------------
  539.   '  uw        0         0            0
  540.  '  0         uh        0            0
  541.  '  0         0         -(f+n)/(f-n) -2fn/(f-n)
  542.  '  0         0         -1           0
  543.  -------------------------------------------------
  544.   r[10] = -(far+near) * i
  545.   r[11] = -1
  546.   r[14] = -2.0 * far * near * i
  547.   r[15] = 0
  548.   end function
  549.  
  550.  
  551.   '===========
  552.  'QUATERNIONS
  553.  '===========
  554.  '
  555.  'http://ogldev.atspace.co.uk/www/tutorial15/tutorial15.html
  556.  'http://www.cprogramming.com/tutorial/3d/quaternions.html
  557.  '
  558.  ' Hamilton
  559.  '
  560.  'SLERP, or Spherical Linear intERPolation
  561.  '
  562.  ' Q = xi + yj + zk + w
  563.  '
  564.  ' i*i == j*j == k*k = ijk == -1
  565.  '
  566.  ' 1/Q == -xi - yi - zk +w
  567.  '
  568.  'ROTATION QUATERNION
  569.  '
  570.  ' W = QVQ^-1
  571.  '
  572.  ' Q = {
  573.  ' v.x * sin(a/2),
  574.  ' v.y * sin(a/2),
  575.  ' v.z * sin(a/2),
  576.  ' cos(a/2)
  577.  ' }
  578.  
  579.   function NormQuaternion(float *r)
  580.   =================================
  581.   indexbase 0
  582.   double f = 1 / sqr(r[0]*r[0] + r[1]*r[1] + r[2]*r[2] + r[3]*r[3])
  583.   r[0]*=f
  584.   r[1]*=f
  585.   r[2]*=f
  586.   r[3]*=f
  587.   end function
  588.  
  589.  
  590.   function SetQuaternion(float *r,a,x,y,z)
  591.   ========================================
  592.   indexbase 0
  593.   a=rad(a/2) 'degrees to radians
  594.  float sa=sin(a)
  595.   r[0]=x*sa
  596.   r[1]=y*sa
  597.   r[2]=z*sa  
  598.   r[3]=cos(a)
  599.   NormQuaternion r
  600.   end function
  601.  
  602.  
  603.   function ResetQuaternion(float *r)
  604.   ==================================
  605.   r={0,0,0,1}
  606.   end function
  607.  
  608.  
  609.   function MulQuaternion(float *r,*a,*b)
  610.   ======================================
  611.   '0 x
  612.  '1 y
  613.  '2 z
  614.  '3 w
  615.  indexbase 0
  616.   'itr test first for deviation from unit
  617.  NormQuaternion a
  618.   NormQuaternion b
  619.   '
  620.  r[3] = a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*[b[2]
  621.   r[0] = a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*[b[1]
  622.   r[1] = a[3]*b[1] - a[0]*b[2] + a[1]*b[3] + a[2]*[b[0]
  623.   r[2] = a[3]*b[2] + a[0]*b[1] - a[1]*b[0] + a[2]*[b[3]
  624.   end function
  625.  
  626.   'generate local_rotation (details later)
  627.  'Qtotal = Qlocal * Qtotal  //multiplication order matters on this line
  628.  '
  629.  '
  630.  function MulQuaternion(float *qTotal,*qLocal)
  631.   =============================================
  632.   float q[4]
  633.   MulQuaternion q,qLocal,qTotal
  634.   copyfloat qTotal,q,4
  635.   end function
  636.  
  637.  
  638.   function MatFromQuat(float *r,*q)
  639.   =================================
  640.   indexbase 0
  641.   r[0]  = 1-2*q[1]*q[1] - 2*q[2]*q[2]
  642.   r[1]  =  2*q[0]*q[1] + 2*q[3]*q[2]
  643.   r[2]  = 2*q[0]*q[2] - 2*q[3]*q[1]
  644.   r[3]  = 0
  645.   r[4]  = 2*q[0]*q[1] - 2 * q[3]*q[2]
  646.   r[5]  = 1 - 2*q[0]*q[0] - 2*q[2]*q[2]
  647.   r[6]  = 2*q[1]*q[2] - 2*q[3]*q[0]
  648.   r[7]  = 0
  649.   r[8]  = 2*q[0]*q[2] + 2*q[3]*q[1]
  650.   r[9]  = 2*q[1]*q[2] + 2*q[3]*q[0]
  651.   r[10] = 1-2*q[0]*q[0] - 2*q[1]*q[1]
  652.   r[11] = 0
  653.   r[12] = 0
  654.   r[13] = 0
  655.   r[14] = 0
  656.   r[15] = 1
  657.   end function
  658.  
  659.  
  660.   ==============================================
  661.   'FUNCTIONS EMULATING CLASSIC OPENGL TRANSFORMS
  662.  ==============================================
  663.  
  664.  
  665.   float MatStack[800], sys MatIdx 'stack depth: 50
  666.  
  667.   identity MatStack,4 : MatIdx=0
  668.  
  669.   function scalef(float x,y,z)
  670.   ============================
  671.   indexbase 0
  672.   float m[32]
  673.   mat4x4scale m[0],x,y,z
  674.   mat4x4mul m[16],MatStack[MatIdx],m[0]
  675.   copymat MatStack[MatIdx],m[16]
  676.   end function
  677.  
  678.  
  679.   function translatef(float x,y,z)
  680.   ================================
  681.   indexbase 0
  682.   float m[32]
  683.   mat4x4translate m[0],x,y,z
  684.   mat4x4mul m[16], MatStack[MatIdx],m[0]
  685.   copymat MatStack[MatIdx],m[16]
  686.   end function
  687.  
  688.  
  689.   function rotatef(float a,x,y,z)
  690.   ===============================
  691.   indexbase 0
  692.   float m[32]
  693.   mat4x4rotate m[0],a,x,y,z
  694.   mat4x4mul m[16],MatStack[MatIdx],m[0]
  695.   copymat MatStack[MatIdx],m[16]
  696.   end function
  697.  
  698.  
  699.   function PushMatrix()
  700.   =====================
  701.   indexbase 0
  702.   sys msd=MatIdx+16
  703.   if msd<800 then
  704.     copymat matstack[msd], matstack[MatIdx]
  705.     MatIdx=msd
  706.   end if
  707.   end function
  708.  
  709.  
  710.   function PopMatrix()
  711.   ====================
  712.   if MatIdx>0 then MatIdx-=16
  713.   end function
  714.  
  715.  
  716.   function LoadIdentity()
  717.   =======================
  718.   indexbase 0
  719.   identity matstack[MatIdx],4
  720.   end function
  721.  
  722.  
  723.   'SUPPORTING FUNCTIONS
  724.  
  725.   function ResetMatrix()
  726.   ======================
  727.   MatIdx=0
  728.   LoadIdentity
  729.   end function
  730.  
  731.   function MulMatrix(float *m)
  732.   ============================
  733.   indexbase 0
  734.   float r[16]
  735.   mat4x4mul r,MatStack[MatIdx],m
  736.   copymat MatStack[MatIdx],r
  737.   end function
  738.  
  739.  
  740.   function inversef()
  741.   ===================
  742.   indexbase 0
  743.   float m[16]
  744.   mat4x4inverse m[0],MatStack[MatIdx]
  745.   copymat MatStack[MatIdx],m[0]
  746.   end function
  747.  
  748.  
  749.   function RotateAxis(float a,x,y,z)
  750.   ==================================
  751.   float q[4], m[16]
  752.   SetQuaternion q,a, x,y,z
  753.   MatFromQuat   m,q
  754.   MulMatrix     m
  755.   end function
  756.  
  757.   function transformf(float *v, int n=1,st=12,oo=0)
  758.   =================================================
  759.   '
  760.  indexbase 0
  761.   float m at (@MatStack[MatIdx])
  762.   float r[3]
  763.   sys i
  764.   @v+=oo 'OFFSET
  765.  n-- 'FINAL VERTEX INDEX
  766.  for i=0 to n
  767.     r[0]  = m[0] * v[0]  + m[4] * v[1]  + m[8]  * v[2]  + m[12]
  768.     r[1]  = m[1] * v[0]  + m[5] * v[1]  + m[9]  * v[2]  + m[13]
  769.     r[2]  = m[2] * v[0]  + m[6] * v[1]  + m[10] * v[2]  + m[14]
  770.     v={r[0],r[1],r[2]}
  771.     @v+=st 'STRIDE
  772.  next
  773.   end function
  774.  
« Last Edit: April 12, 2015, 05:21:22 AM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #1 on: April 12, 2015, 07:02:34 AM »
Very nice! :)

Normalization, rotation, etc. functions that contain 1/sqr should be protected against sqr=0 by setting it to 1. It does happen in real world scenarios every now and then. E.g. many low quality meshes would contain the so-called "flat" (a.k.a. "degenerate") triangles with zero area, undefined normals, etc.

FBSL has a built-in vector and matrix maths library with more or less uniform sets of identical functions for single-precision vector2, vector3, vector4, plane, quaternion, and matrix4 transforms (~40KB of machine code). I'm planning to also add 2D and 3D sphere and box collision detection to it.

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #2 on: April 12, 2015, 11:20:37 AM »
Hi Mike,

Something like:

Code: OxygenBasic
  1. 'Normalize
  2. float f=sqr(x*x+y*y+z*z)
  3. if f then f=1/f else exit sub
  4. x*=f : y*=f : z*=f
  5.  

Matrices and Quaternions are pure genius, but trying to unravel them might cause one's head to explode. :o

Nonetheless it was very gratifying to test these functions and see them working.



I found a comprehensive series of tutorials on Modern Opengl here:

http://ogldev.atspace.co.uk



Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #3 on: April 12, 2015, 01:26:26 PM »
Hi Charles,

Something like:

Exactly. Just make sure that the other functions where 1/sqr occurs can stand such a simple return without any calculations. I vaguely recollect some functions from my experience that actually required the calc to go on with this funny 1/1 factor to produce a valid output. It's just a convention that the div by zero error be remedied with 1 in such cases but filling the output structure with a meaningful value may still require code execution rather than early bail out.

Quote
Matrices and Quaternions are pure genius, but trying to unravel them might cause one's head to explode. :o
Nonetheless it was very gratifying to test these functions and see them working.

Quaternions are a blessing. They are so much more computationally lightweight than matrices. Ultimately, everything in 3D can be described in quaternion-assisted rotations. Translations are but a special case of rotation around an infinitely distant axis. :)

Quote
I found a comprehensive series of tutorials on Modern Opengl here:

Very cool! But us old farts simply can't let go of such fossils like 32 bits, draw lists, or fixed-function pipeline. It seems like by doing so, we'll be amputating somethings that literally grew into our flesh and blood. :)

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #4 on: April 13, 2015, 10:37:26 AM »
Mike,

I have been  looking ahead at geometry instancing as a possible substitute for glLists. It is much more involved, and not really a good fit for those of us who like to build stuff out of geometric primitives.

So I think the old farts must continue to have their way :)

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #5 on: April 15, 2015, 01:24:29 AM »
Tip for improving code readability:

This is a remedy for excessively long Opengl names :)

If macros are defined inside a procedure, they have local scope, so you can create ad-hoc definitions that will not interfere with other parts of the program.

Code: OxygenBasic
  1.   % lookup %1 = glGetAttribLocation ShaderP, "%1"
  2.   lookup v_vertex
  3.   lookup v_normal
  4.   lookup v_texcor
  5.   lookup v_color
  6.   '
  7.  % enable glEnableVertexAttribArray %1
  8.   enable v_vertex
  9.   enable v_normal
  10.   enable v_texcor
  11.   enable v_color
  12.  

Full MakeVBO procedure

Code: OxygenBasic
  1.   sub MakeVBO
  2.   ===========
  3.   '
  4.  if shaderError then exit sub
  5.   static float t={
  6.    'vertex   normal  texcor color
  7.   '-------------------------------
  8.    0, 1,0,  0,0,1,  .0,1,  1,0,0,1,
  9.    -1,-1,0,  0,0,1, -.5,0,  0,1,0,1,
  10.     1,-1,0,  0,0,1,  .5,0,  0,0,1,1
  11.    '-------------------------------
  12.  }
  13.   '
  14.  % lookup %1 = glGetAttribLocation ShaderP, "%1"
  15.   lookup v_vertex
  16.   lookup v_normal
  17.   lookup v_texcor
  18.   lookup v_color
  19.   '
  20.  % enable glEnableVertexAttribArray %1
  21.   enable v_vertex
  22.   enable v_normal
  23.   enable v_texcor
  24.   enable v_color
  25.   '
  26.  glGenBuffers  1, vbo
  27.   glBindBuffer GL_ARRAY_BUFFER, vbo
  28.   glBufferData GL_ARRAY_BUFFER, bytesof t, @t, GL_STATIC_DRAW
  29.   '
  30.  % vap   =  glVertexAttribPointer
  31.   % f     =  GL_FLOAT
  32.   % n     =% 12*sizeof float 'stride
  33.  '
  34.  'call attribute n  type nrm stride offset
  35.  '----------------------------------------
  36.  vap   v_vertex, 3, f,   0,  n,     00  '0
  37.  vap   v_normal, 3, f,   0,  n,     12  '3
  38.  vap   v_texcor, 2, f,   0,  n,     24  '6
  39.  vap   v_color , 4, f,   0,  n,     32  '8
  40.  '----------------------------------------
  41.  end sub
  42.  

Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #6 on: April 15, 2015, 09:35:10 AM »
Tip for improving code readability:

which reminds me ... :)


When FBSL v3 was yet at its very, very early stages being essentially a BP.org-style bare-bones console-only BASIC interpreter, there was a man in our dev team, a young but brilliant French fellow Mehdi Bouaziz, who had an absolutely phenomenal ability to generate loads of C code for days and nights at a stretch. The code wasn't particularly neat, style-wise, but damn, it worked! It did just what it was supposed to and it improved by the hour as the rest of us sat around inventing more and more test cases to drive Mehdi into a trap.

He was mastering the various aspects of C programming and improving his skills as he worked his way through FBSL. He wrote FBSL's BASIC bytecode compiler and optimizer as an exercise to train himself in the C preprocessor "language" before the nearest IOI (International Olympiad in Informatics), which brought him a gold medal.

Guys, it took me literally years to revert those several files back to readable C. Otherwise the code was totally, absolutely, ultimately unmaintainable. :)

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #7 on: April 15, 2015, 11:48:14 AM »

It is like walking into a cave system of many tunnels, then pulling the string which traces the way back. The intent of the code is often concealed, as more pieces are added.

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #8 on: April 17, 2015, 04:14:21 AM »
Shader Instancing

The shape, or group of shapes, is passed once to the shader, then a bunch of matrices are passed to the shader, as instances, specifiying position, scale, and rotation. This enables multiple instances of the same object to be rendered in one call.

Good for large populations of buildings, trees, rocks etc.

glDrawElementsInstancedBaseVertexBaseInstance( GL_TRIANGLES, 3, GL_UNSIGNED_INT, null, 3, 0, 0 ) :o

current project: examples\opengl\glMathTest\glMath7.o2bas




.

Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #9 on: April 17, 2015, 04:47:13 AM »
Good for large populations of buildings, trees, rocks etc.

Not only that, Charles! Geometry instancing is the only feasible way to render massively animated objects such as crowds of fans at a stadium or fighters in a battle field, or a million trees in the forest.

Quote
glDrawElementsInstancedBaseVertexBaseInstance( GL_TRIANGLES, 3, GL_UNSIGNED_INT, null, 3, 0, 0 ) :o

Hehehehehe....
« Last Edit: April 17, 2015, 02:25:58 PM by Mike Lobanovsky »

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #10 on: April 17, 2015, 12:29:26 PM »

I am looking forward to some geometry hardcore :). Unfortunately my Nvidia card of 2009 vintage, does not support tessellation, but it can do geometry shaders and most other shader4 things.

Do you know whether shader4 spec is commonplace on the cheaper graphics cards of today, Mike?

Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #11 on: April 17, 2015, 02:51:49 PM »
Hi Charles,

AFAIK
  • Shader Model 4 and DX 10 start somewhere at nVidia 8XXX/9XXX/GT200+ and ATI X2400+
  • Shader Model 4.1 and DX 10.1, at nVidia GT220+ and ATI HD3000+
  • Shader Model 5 and DX 11, at nVidia GT400+ and ATI HD5000+
Intel doesn't go higher than Shader Model 4.

So, I'd say pretty much every discrete nVidia/ATI graphics card bought in recent 2 or 3 years would support Shader Model 4 in its entirety. Older models like yours or mine may have a couple features occasionally missing here and there due to some minor differences in video chip topology of certain makes and OEM vendors aimed at bringing down the end price.

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #12 on: April 19, 2015, 12:27:58 AM »
Thank you Mike,

The hardware guys are well ahead of us.

The necessary information is scattered all over the web but I eventually got the Geometry shader working, with instancing in GLSL 3.3

This is what the shaders look like:

Vertex Shader
Code: [Select]
  Shader.vsrc="
  #version 330
  uniform mat4 projection;
  uniform mat4 modelView;
  layout (location = 0) in   vec3 v_vertex;
  layout (location = 1) in   vec3 v_normal;
  layout (location = 2) in   vec2 v_texcor;
  layout (location = 3) in   vec4 v_color;
  layout (location = 4) in   mat4 v_matrix;

  out vData
  {
    vec4 position;
    vec3 normal;
    vec4 color;
  }vertex;

  void main(void) {
    mat4 m = modelView * v_matrix;
    vertex.position = projection * m * vec4(v_vertex, 1.0);
    vertex.normal   = normalize ( transpose ( inverse ( mat3 ( m ) ) ) * v_normal );
    vertex.color    = v_color;
  }

Geometry Shader
Code: [Select]
  #version 330
  #extension GL_ARB_geometry_shader4 : enable
  layout(triangles) in;
  layout(triangle_strip, max_vertices=6) out;
  int  i;
  in vData
  {
    vec4 position;
    vec3 normal;
    vec4 color;
  }vertex[];
 
  out fData
  {
    vec4 position;
    vec3 normal;
    vec4 color;
  }frag;
 
 
  void main()
  {
   for(i = 0; i < gl_VerticesIn; i++ )
   {
     gl_Position = vertex[i].position;
     frag.color = vertex[i].color;
     EmitVertex();
   }
   EndPrimitive();

   //New piece of geometry!
   vec4 v;
   for(i = 0; i < gl_VerticesIn; i++)
   {
     v = vertex[i].position;
     //displace along the normal
     v = v + 0.25 * vec4(vertex[i].normal,0.0);
     gl_Position = v;
     frag.color = vertex[i].color;
     EmitVertex();
   }
   EndPrimitive();
  }

Fragment Shader
Code: [Select]
  #version 330
  in fData
  {
    vec4 position;
    vec3 normal;
    vec4 color;
  }frag;

  layout(location = 0) out vec4 color;

  void main(void) {
    color = frag.color;
  }

Pieces of code to cling onto :)



.

Mike Lobanovsky

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #13 on: April 19, 2015, 12:42:46 AM »
Hehe, cool!

You've got a spare uniform v_texcor BTW.

Awaiting instanced textured objects I remain

Sincerely yours,

etc. etc. etc. :D

Charles Pegge

  • Guest
Re: Matrix and Quaternion Hardcore
« Reply #14 on: April 19, 2015, 12:51:47 AM »
Yes, yes. More baggage to follow. Actually version 330 allows pretty clean abstract code. Easier to read and maintain. But would it be better in Scheme ? :)