WebGL Matrix Transformation Utility

Initialization JavaScript Source Code

Constructor Protoype Methods Intersecting Planes Model Mesh Intersecting Planes Texture Map

Source code to initialize the WebGL Matrix Transformation Utility.

Meshes load and display with JavaScript and shaders described in the WebGL EBook Series Online 3D Media with WebGL. The JavaScript presented here includes comments which explain how to use the source code to display your own mesh elements with the Matrix Transformation Utility.

GLModelLoad.js Constructor

/**
*Display one mesh
*with WebGL.
*
*@param s:String path to
*image file for use as WebGLTexture.
*  
*Extensible: Add more mesh
*elements to the interleaved
*Float32Array.
*Add new values to
*arrays aOffset and aCount,
*which indicate where
*to begin and end drawing
*each new mesh.
 */
var GLModelLoad = function(s){
 
// Substitute Planes()
// with any model data.
// which includes:
 
// 'aVertices', Float32Array of interleaved
// vertices and texels.
// Upload to GPU
// as ARRAY_BUFFER.
 
// 'aIndices', Uint16Array of indices.
// Upload to GPU as
// ELEMENT_ARRAY_BUFFER.
 
// Includes array of
// offsets into Uint16Array
// named aOffsets.
// Includes array of
// count into Uint16Array
// named aCount.
var shape = new Planes(); 
 
var aIm = new Array();
 
// 's' parameter
// is the map for the shape.
var e =  new GLEntity(
 s,
 0
);
 
// The first offset.
e.nOffset = Number(
 shape.aOffset[0]
);
 
// The first count.
e.nCount = Number(
 shape.aCount[0]
); 

aIm.push(e);  

var controller = new GLControl
(
 shape.aVertices,
 shape.aIndices,  
 aIm,
 this
);
  
if(controller == null){
 return;
} 
 
var btTransform = document.getElementById(
'btnTransform'
);

if (btTransform != null){
 this.assignTransformer(
  btnTransform,
  controller
 );
}

};

GLModelLoad.jsProtoype Methods

GLModelLoad.prototype = {

/***
 * Prepare listeners and data
 * for interactive transformations.
 */
assignTransformer: function(btnTransform,controller){
 
 btnTransform.controller = controller;
 btnTransform.addEventListener(
  'click',
  this.clickBtnTransform,
  false
 );
 
 // Click the canvas to see the transform as well.
 controller.cv.addEventListener(
  'click',
  this.clickBtnTransform,
  false
 );
 
 var btnReset = document.getElementById(
  'btnReset'
 );
 btnReset.controller = controller;
 btnReset.addEventListener(
  'click',
  this.clickBtnReset,
  false
 );
 
 var btnReset = document.getElementById(
  'btnBoxes'
 );
 btnReset.controller = controller;
 btnReset.addEventListener(
  'click',
  this.clickBtnResetBoxes,
  false
 );
 
 this.aRotation = new Array();
 this.aRotation.push(
  document.getElementById('nRX')
 );
 this.aRotation.push(
  document.getElementById('nRY')
 );
 this.aRotation.push(
  document.getElementById('nRZ')
 );
 
 this.aTranslation = new Array();
 this.aTranslation.push(
  document.getElementById('nTX')
 );
 this.aTranslation.push(
  document.getElementById('nTY')
 );
 this.aTranslation.push(
  document.getElementById('nTZ')
 );
 
 this.aScale = new Array();
 this.aScale.push(
  document.getElementById('nSX')
 );
 this.aScale.push(
  document.getElementById('nSY'
 ));
 this.aScale.push(
  document.getElementById('nSZ')
 );
 

 // Default transformation
 // matrix for Planes.
 // One unit from the viewport.
 this.MATRIX_DEFAULT = (
   [
     0.035, 0, 0, 0,
     0, 0.035, 0, 0,
     0, 0, 0.035, 0,
     0, 0, -1, 1
   ] 
  );
 
},

/**
 * Provides transformations
 * in response to button click.
 */
clickBtnTransform: function(ev){
 var controller = ev.currentTarget.controller;
 var e = controller.aEntities[0];
 var glDemo = controller.glDemo; 
 var eDebug = controller.eDebug;

 var aRotation = controller.glDemo.aRotation;
 var aTranslation = controller.glDemo.aTranslation;
 var aScale = controller.glDemo.aScale; 

 var nRX = parseFloat(aRotation[0].value);
 var nTX = parseFloat(aTranslation[0].value);
 var nSX = parseFloat(aScale[0].value);
 
 var nRY = parseFloat(aRotation[1].value);
 var nTY = parseFloat(aTranslation[1].value);
 var nSY = parseFloat(aScale[1].value);

 var nRZ = parseFloat(aRotation[2].value);
 var nTZ = parseFloat(aTranslation[2].value);
 var nSZ = parseFloat(aScale[2].value);
 
 var matrixMod= mat4.create();

  
 mat4.set(e.matrix, matrixMod);
 
 // Cumulative transformations.
 // Order translate, rotate, scale, 
 // does matter.
 // But the user can assign
 // defaults to the Web page's
 // matrix input fields.
 if (nTX != 0 || nTY != 0 || nTZ != 0){
  mat4.translate(matrixMod,[nTX,nTY,nTZ]);
 }

 if (nRX != 0){
  mat4.rotate(matrixMod,nRX,[1,0,0]);
 }
 if (nRY != 0){
  mat4.rotate(matrixMod,nRY,[0,1,0]);
 }
 if (nRZ != 0){
  mat4.rotate(matrixMod,nRZ,[0,0,1]);
 } 
 
 if (nSX != 1 || nSY != 1 || nSZ != 1 ){
  mat4.scale(matrixMod,[nSX,nSY,nSZ]);
 }

 mat4.set(matrixMod,e.matrix);
 window.location = '#cv';
 glDemo.nX = glDemo.nY = glDemo.nMiddle;
 controller.render(controller);
 
 eDebug.innerHTML +="<br />Translate: X:"+nTX+",Y:"+nTY+",Z:"+nTZ+"<br />";
 eDebug.innerHTML +="Rotate: X:"+nRX+",Y:"+nRY+",Z:"+nRZ+"<br />";
 eDebug.innerHTML +="Scale: X:"+nSX+",Y:"+nSY+",Z:"+nSZ+"<br />";
},

/**
 * Assign default values
 * to the Web page
 * and meshe entitie's matrix.
 */
reset: function(controller,glDemo){
 var e = controller.aEntities[0];
 
 var MATRIX_DEFAULT = controller.glDemo.MATRIX_DEFAULT;
 
 for (var i = 0; i < e.matrix.length; i++){
  e.matrix[i] = MATRIX_DEFAULT[i];
 }
 
 glDemo.resetBoxes(glDemo);
 
 glDemo.nX = glDemo.nY = glDemo.nMiddle;
 
 controller.render(
  controller
 );
},

resetBoxes: function(glDemo){

 var aRotation = glDemo.aRotation;
 var aTranslation = glDemo.aTranslation;
 var aScale = glDemo.aScale;
 
 for (var i = 0; i < 3; i++){
  aRotation[i].value = "0";
  aTranslation[i].value = "0";
  aScale[i].value = "1";
 }
 
},

/**
 * Call reset from
 * button click.
 */
clickBtnReset: function(ev){

 var controller = ev.currentTarget.controller;
 var glDemo = controller.glDemo;
 
 glDemo.reset(
  controller,
  glDemo
 );

 controller.eDebug.innerHTML = "";
},
 
/**
 * Call reset from
 * button click.
 */
clickBtnResetBoxes: function(ev){

 var controller = ev.currentTarget.controller;
 
 var glDemo = controller.glDemo;
 
 glDemo.resetBoxes(
  glDemo
 ); 
},

init:function(controller) {
 var gl = controller.gl;
 var glDemo = controller.glDemo;
 var glUtils = controller.glUtils = new GLUtils();
 var e = controller.aEntities[0];
 var matrixMod = mat4.create();

 e.render = glDemo.renderStationary;
 glDemo.reset(controller,glDemo); 
 
gl.activeTexture(
 gl.TEXTURE0 + e.idx
);
       
gl.texParameteri
(
 gl.TEXTURE_2D, 
 gl.TEXTURE_MAG_FILTER, 
 gl.LINEAR 
); 
      
gl.texParameteri
(
 gl.TEXTURE_2D, 
 gl.TEXTURE_MIN_FILTER, 
 gl.LINEAR 
);   
 
 gl.enable
 (
   gl.DEPTH_TEST
 ); 
 

},

/**
 * Just displays one render frame,
 * based on the current transformation
 * matrix.
 */
renderStationary: function(controller,e){

 var gl = controller.gl;
 
 gl.uniformMatrix4fv
 (
  controller.uMatrixTransform, 
  false, 
  new Float32Array
  (
    e.matrix
  )
 );    

 gl.drawElements
 (
  gl.TRIANGLES, 
  e.nCount, 
  gl.UNSIGNED_SHORT, 
  e.nOffset
 );  
},

/**
 * 
 */
render:function(controller){

 var entity = controller.aEntities[0];
 
 entity.render(
  controller,
  entity
 ); 
},

};

Intersecting Planes Model Mesh Planes.js

JavaScript source file Planes.js displays three perpendicular planes. The file simply contains model data for meshes. Substitute vertices, texels, and indices to display your own mesh in the Matrix Transformation Utility.

var Planes = function(){
 
// Interleaved
// three vertices,
// then two texels.
// Upload as an ARRAY_BUFFER.
this.aVertices = new Float32Array([
-10,-10,0,
0.02,0.508172,
10,-10,0,
0.491828,0.508172,
10,10,0,
0.491828,0.98,
10,10,0,
0.491828,0.98,
-10,10,0,
0.02,0.98,
-10,-10,0,
0.02,0.508172,
0.000002,-10,-10,
0.491828,0.02,
-0.000001,-10,10,
0.491828,0.491828,
-0.000002,10,10,
0.02,0.491828,
-0.000002,10,10,
0.02,0.491828,
0.000001,10,-10,
0.02,0.02,
0.000002,-10,-10,
0.491828,0.02,
-10,0.000000,10,
0.98,0.491828,
10,0.000000,10,
0.508172,0.491828,
10,-0.000000,-10,
0.508172,0.02,
10,-0.000000,-10,
0.508172,0.02,
-10,-0.000000,-10,
0.98,0.02,
-10,0.000000,10,
0.98,0.491828,
]);

// Indices
// Upload as an
// ELEMENT_ARRAY_BUFFER
this.aIndices = new Uint16Array([
0,1,2,
3,4,5,
6,7,8,
9,10,11,
12,13,14,
15,16,17,
]);

// Offset into
// the buffer to
// begin drawing operations.
this.aOffset = [0];

// Number of elements
// to draw.
this.aCount = [
 this.aIndices.length
];
};

Intersecting Planes Texture Map

Intersecting Planes Texture Map

Baked Plane Texture
Copyright © 2015 Seven Thunder Software. All Rights Reserved.