示例#1
0
function invert(out, M) {
  switch(M.length) {
    case 0:
    break
    case 1:
      out[0] = 1.0 / M[0]
    break
    case 4:
      invert2(out, M)
    break
    case 9:
      invert3(out, M)
    break
    case 16:
      invert4(out, M)
    break
    default:
      throw new Error('currently supports matrices up to 4x4')
    break
  }
  return out
}
示例#2
0
文件: gltf.js 项目: pex-gl/pex-next
  loadGLTF: function() {
    var gl = this.gl;
    var commands = this.commands;
    var showNormalsProgram = this.showNormalsProgram;
    var projectionMatrix = this.camProjectionMatrix;
    var viewMatrix = this.viewMatrix;
    var modelMatrix = this.boxModelMatrix;
    var modelViewMatrix = mult44(createMat4(), viewMatrix, modelMatrix);
    var normalMatrix = createMat4();
    invert(normalMatrix, modelViewMatrix);
    transpose(normalMatrix, normalMatrix);
    normalMatrix = [
      normalMatrix[0], normalMatrix[1], normalMatrix[2],
      normalMatrix[4], normalMatrix[5], normalMatrix[6],
      normalMatrix[8], normalMatrix[9], normalMatrix[10]
    ];

    //loadGLTF(gl, __dirname + '/assets/model/box/box.gltf', function(err, json) {
    //loadGLTF(gl, __dirname + '/assets/model/duck/duck.gltf', function(err, json) {
    //loadGLTF(gl, __dirname + '/assets/model/wine/wine.gltf', function(err, json) {
    //loadGLTF(gl, __dirname + '/assets/model/SuperMurdoch/SuperMurdoch.gltf', function(err, json) {
    loadGLTF(gl, __dirname + '/assets/model/rambler/Rambler.gltf', function(err, json) {
      if (err) {
        log('load done', 'err:', err);
      }
      else {
        log('load done',  '' + json);
      }

      var bbox = {
        min: [Infinity, Infinity, Infinity],
        max: [-Infinity, -Infinity, -Infinity]
      };

      log('buildMesh');
      forEachKeyValue(json.meshes, function(meshName, meshInfo, meshIndex) {
        meshInfo.primitives.forEach(function(primitiveInfo, primitiveIndex) {
          if (!primitiveInfo.vertexArray) return; //FIXME: TEMP!

          var materialInfo = json.materials[primitiveInfo.material];
          var instanceValues = materialInfo.instanceTechnique.values;
          var techniqueInfo = json.techniques[materialInfo.instanceTechnique.technique];
          var parameters = techniqueInfo.parameters;
          var defaultPass = techniqueInfo.passes.defaultPass;
          var instanceProgramInfo = defaultPass.instanceProgram;
          var program = json.programs[instanceProgramInfo.program]._program;

          var uniforms = {};
          var localModelViewMatrix = createMat4();

          //projectionMatrix: projectionMatrix,
          //viewMatrix: viewMatrix,
          //modelMatrix: modelMatrix

          forEachKeyValue(instanceProgramInfo.uniforms, function(uniformName, valueName) {
            var parameter = parameters[valueName];
            var value = instanceValues[valueName] || parameter.value;
            uniforms[valueName] = null;
            //log('uniform', uniformName, valueName, value, parameter);
            if (!value) {
              if (parameter.source) {
                  log('uniform source found', parameter.source);  //TODO: uniform source
                  //TODO: is source refering only to node matrices?
                  value = json.nodes[parameter.source].matrix;
              }
              else if (parameter.semantic) {
                switch(parameter.semantic) {
                  case 'MODELVIEW':
                    copy44(localModelViewMatrix, modelViewMatrix);
                    value = localModelViewMatrix;
                    break;
                  case 'PROJECTION':
                    value = projectionMatrix;
                    break;
                  case 'MODELVIEWINVERSETRANSPOSE':
                    value = normalMatrix;
                    break;
                  default:
                    throw new Error('Unknown uniform semantic found ' + parameter.semantic);
                }
              }
              else {
                throw new Error('No value for uniform:' + valueName);
              }
            }
            if (instanceValues[valueName]) {
              switch(parameters[valueName].type) {
                case gl.SAMPLER_2D:
                  value = json.textures[value]._texture;//TODO: check if this is not null (eg. texture loading failed)
                  break;
                case gl.FLOAT_VEC2: break;
                case gl.FLOAT_VEC3: break;
                case gl.FLOAT_VEC4: break;
                case gl.FLOAT_MAT4: break;
                case gl.FLOAT: break;
                default:
                  throw new Error('Unknown uniform type:' + parameters[valueName].type);
              }
            }

            if (value === null || value === undefined) {
              throw new Error('Uniform ' + valueName + ' is missing');
            }
            uniforms[valueName] = value;
          });

          //program = showNormalsProgram;

          forEachKeyValue(uniforms, function(name, value) {
            uniforms['u_' + name] = value;
            delete uniforms[name];
          })

          var positions = primitiveInfo.vertexArray.attributes['position'].dataBuf;
          for(var i=0; i<positions.length; i+=3) {
            for(var j=0; j<3; j++) {
              bbox.min[j] = Math.min(bbox.min[j], positions[i+j]);
              bbox.max[j] = Math.max(bbox.max[j], positions[i+j]);
            }
          }

          meshInfo._cmd = {
            vertexArray : primitiveInfo.vertexArray,
            program     : program,
            uniforms    : uniforms,
            renderState : {
              depthTest: true
            },
            bbox: bbox
          }

          //var cmd = new DrawCommand({
          //  vertexArray : primitiveInfo.vertexArray,
          //  program     : program,
          //  uniforms    : uniforms,
          //  renderState : {
          //    depthTest: true
          //  }
          //});
          //commands.push(cmd);
        });
      });

      forEachKeyValue(json.nodes, function(nodeName, nodeInfo, nodeIndex) {
        var localMatrix = createMat4();
        scale44(localMatrix, localMatrix, [2, -2, 2])
        translate(localMatrix, localMatrix, [-2, 0, 0])
        var matrixStack = [nodeInfo.matrix];
        var parent = nodeInfo.parent;
        while(parent) {
          if (parent.matrix) {
            matrixStack.unshift(parent.matrix);
          }
          parent = parent.parent;
        }
        matrixStack.forEach(function(mat) {
          mult44(localMatrix, localMatrix, mat);
        })
        if (nodeInfo.meshes) {
          nodeInfo.meshes.forEach(function(meshId) {
            var mesh = json.meshes[meshId];
            var cmd = new DrawCommand(mesh._cmd);
            mult44(cmd.uniforms.u_modelViewMatrix, cmd.uniforms.u_modelViewMatrix, localMatrix);
            commands.push(cmd);
          })
        }
      });

      var size = sub3([0,0,0], bbox.max, bbox.min);
      var maxScale = Math.max(size[0], Math.max(size[1], size[2]))
      //console.log(maxScale)
      //maxScale = 0.05;
      var tmp = createMat4();
      commands.forEach(function(cmd, cmdIndex) {
        if (!cmd.uniforms) return;
        //translate(cmd.uniforms.u_modelViewMatrix, cmd.uniforms.u_modelViewMatrix, [-size[0]/2, -size[1]/2, -size[2]/2]);
        //translate(cmd.uniforms.u_modelViewMatrix, cmd.uniforms.u_modelViewMatrix, [-0.1, 0, 0]);
        //scale44(cmd.uniforms.u_modelViewMatrix, cmd.uniforms.u_modelViewMatrix, [1/maxScale, 1/maxScale,1/maxScale]);
        //console.log('cmd', cmdIndex, cmd.vertexArray.indexBuffer.dataBuf.length)
      })
    });
  },
示例#3
0
function drawCore(params, transparent) {
  params = params || {}
  var gl = this.gl

  gl.disable(gl.CULL_FACE)

  this._colorMap.bind(0)

  var uniforms = UNIFORMS
  uniforms.model        = params.model || IDENTITY
  uniforms.view         = params.view || IDENTITY
  uniforms.projection   = params.projection || IDENTITY
  uniforms.lowerBound   = this.bounds[0]
  uniforms.upperBound   = this.bounds[1]
  uniforms.contourColor = this.contourColor[0]

  uniforms.inverseModel = invert(uniforms.inverseModel, uniforms.model)

  for(var i=0; i<2; ++i) {
    var clipClamped = uniforms.clipBounds[i]
    for(var j=0; j<3; ++j) {
      clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8)
    }
  }

  uniforms.kambient   = this.ambientLight
  uniforms.kdiffuse   = this.diffuseLight
  uniforms.kspecular  = this.specularLight

  uniforms.shape = 

  uniforms.roughness  = this.roughness
  uniforms.fresnel    = this.fresnel
  uniforms.opacity    = this.opacity

  uniforms.height = 0.0
  uniforms.permutation = DEFAULT_PERM

  //Compute camera matrix inverse
  var invCameraMatrix = MATRIX_INVERSE
  multiply(invCameraMatrix, uniforms.view, uniforms.model)
  multiply(invCameraMatrix, uniforms.projection, invCameraMatrix)
  invert(invCameraMatrix, invCameraMatrix)

  for(var i=0; i<3; ++i) {
    uniforms.eyePosition[i] = invCameraMatrix[12+i] / invCameraMatrix[15]
  }

  var w = invCameraMatrix[15]
  for(var i=0; i<3; ++i) {
    w += this.lightPosition[i] * invCameraMatrix[4*i+3]
  }
  for(var i=0; i<3; ++i) {
    var s = invCameraMatrix[12+i]
    for(var j=0; j<3; ++j) {
      s += invCameraMatrix[4*j+i] * this.lightPosition[j]
    }
    uniforms.lightPosition[i] = s / w
  }

  var projectData = computeProjectionData(uniforms, this)

  if(projectData.showSurface && (transparent === (this.opacity < 1))) {
    //Set up uniforms
    this._shader.bind()
    this._shader.uniforms = uniforms

    //Draw it
    this._vao.bind()

    if(this.showSurface) {
      this._vao.draw(gl.TRIANGLES, this._vertexCount)
    }

    //Draw projections of surface
    for(var i=0; i<3; ++i) {
      if(!this.surfaceProject[i]) {
        continue
      }
      this._shader.uniforms.model = projectData.projections[i]
      this._shader.uniforms.clipBounds = projectData.clipBounds[i]
      this._vao.draw(gl.TRIANGLES, this._vertexCount)
    }

    this._vao.unbind()
  }

  if(projectData.showContour && !transparent) {
    var shader = this._contourShader

    //Don't apply lighting to contours
    uniforms.kambient = 1.0
    uniforms.kdiffuse = 0.0
    uniforms.kspecular = 0.0
    uniforms.opacity = 1.0

    shader.bind()
    shader.uniforms = uniforms

    //Draw contour lines
    var vao = this._contourVAO
    vao.bind()

    //Draw contour levels
    for(var i=0; i<3; ++i) {
      shader.uniforms.permutation = PERMUTATIONS[i]
      gl.lineWidth(this.contourWidth[i])

      for(var j=0; j<this.contourLevels[i].length; ++j) {
        if(j === this.highlightLevel[i]) {
          shader.uniforms.contourColor = this.highlightColor[i]
          shader.uniforms.contourTint  = this.highlightTint[i]

        } else if(j === 0 || (j-1) === this.highlightLevel[i]) {
          shader.uniforms.contourColor = this.contourColor[i]
          shader.uniforms.contourTint  = this.contourTint[i]
        }
        shader.uniforms.height = this.contourLevels[i][j]
        vao.draw(gl.LINES, this._contourCounts[i][j], this._contourOffsets[i][j])
      }
    }

    //Draw projections of surface
    for(var i=0; i<3; ++i) {
      shader.uniforms.model      = projectData.projections[i]
      shader.uniforms.clipBounds = projectData.clipBounds[i]
      for(var j=0; j<3; ++j) {
        if(!this.contourProject[i][j]) {
          continue
        }
        shader.uniforms.permutation = PERMUTATIONS[j]
        gl.lineWidth(this.contourWidth[j])
        for(var k=0; k<this.contourLevels[j].length; ++k) {
          if(k === this.highlightLevel[j]) {
            shader.uniforms.contourColor  = this.highlightColor[j]
            shader.uniforms.contourTint   = this.highlightTint[j]
          } else if(k === 0 || (k-1) === this.highlightLevel[j]) {
            shader.uniforms.contourColor  = this.contourColor[j]
            shader.uniforms.contourTint   = this.contourTint[j]
          }
          shader.uniforms.height = this.contourLevels[j][k]
          vao.draw(gl.LINES, this._contourCounts[j][k], this._contourOffsets[j][k])
        }
      }
    }
    
    //Draw dynamic contours
    vao = this._dynamicVAO
    vao.bind()

    //Draw contour levels
    for(var i=0; i<3; ++i) {
      if(this._dynamicCounts[i] === 0) {
        continue
      }

      shader.uniforms.model       = uniforms.model
      shader.uniforms.clipBounds  = uniforms.clipBounds
      shader.uniforms.permutation = PERMUTATIONS[i]
      gl.lineWidth(this.dynamicWidth[i])

      shader.uniforms.contourColor = this.dynamicColor[i]
      shader.uniforms.contourTint  = this.dynamicTint[i]
      shader.uniforms.height       = this.dynamicLevel[i]
      vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i])

      for(var j=0; j<3; ++j) {
        if(!this.contourProject[j][i]) {
          continue
        }

        shader.uniforms.model      = projectData.projections[j]
        shader.uniforms.clipBounds = projectData.clipBounds[j]
        vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i])
      }
    }

    vao.unbind()
  }
}
示例#4
0
module.exports = function decomposeMat4(matrix, translation, scale, skew, perspective, quaternion) {
    if (!translation) translation = [0,0,0]
    if (!scale) scale = [0,0,0]
    if (!skew) skew = [0,0,0]
    if (!perspective) perspective = [0,0,0,1]
    if (!quaternion) quaternion = [0,0,0,1]

    //normalize, if not possible then bail out early
    if (!normalize(tmp, matrix))
        return false

    // perspectiveMatrix is used to solve for perspective, but it also provides
    // an easy way to test for singularity of the upper 3x3 component.
    clone(perspectiveMatrix, tmp)

    perspectiveMatrix[3] = 0
    perspectiveMatrix[7] = 0
    perspectiveMatrix[11] = 0
    perspectiveMatrix[15] = 1

    // If the perspectiveMatrix is not invertible, we are also unable to
    // decompose, so we'll bail early. Constant taken from SkMatrix44::invert.
    if (Math.abs(determinant(perspectiveMatrix) < 1e-8))
        return false

    var a03 = tmp[3], a13 = tmp[7], a23 = tmp[11],
            a30 = tmp[12], a31 = tmp[13], a32 = tmp[14], a33 = tmp[15]

    // First, isolate perspective.
    if (a03 !== 0 || a13 !== 0 || a23 !== 0) {
        tmpVec4[0] = a03
        tmpVec4[1] = a13
        tmpVec4[2] = a23
        tmpVec4[3] = a33

        // Solve the equation by inverting perspectiveMatrix and multiplying
        // rightHandSide by the inverse.
        // resuing the perspectiveMatrix here since it's no longer needed
        var ret = invert(perspectiveMatrix, perspectiveMatrix)
        if (!ret) return false
        transpose(perspectiveMatrix, perspectiveMatrix)

        //multiply by transposed inverse perspective matrix, into perspective vec4
        vec4multMat4(perspective, tmpVec4, perspectiveMatrix)
    } else { 
        //no perspective
        perspective[0] = perspective[1] = perspective[2] = 0
        perspective[3] = 1
    }

    // Next take care of translation
    translation[0] = a30
    translation[1] = a31
    translation[2] = a32

    // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
    mat3from4(row, tmp)

    // Compute X scale factor and normalize first row.
    scale[0] = vec3.length(row[0])
    vec3.normalize(row[0], row[0])

    // Compute XY shear factor and make 2nd row orthogonal to 1st.
    skew[0] = vec3.dot(row[0], row[1])
    combine(row[1], row[1], row[0], 1.0, -skew[0])

    // Now, compute Y scale and normalize 2nd row.
    scale[1] = vec3.length(row[1])
    vec3.normalize(row[1], row[1])
    skew[0] /= scale[1]

    // Compute XZ and YZ shears, orthogonalize 3rd row
    skew[1] = vec3.dot(row[0], row[2])
    combine(row[2], row[2], row[0], 1.0, -skew[1])
    skew[2] = vec3.dot(row[1], row[2])
    combine(row[2], row[2], row[1], 1.0, -skew[2])

    // Next, get Z scale and normalize 3rd row.
    scale[2] = vec3.length(row[2])
    vec3.normalize(row[2], row[2])
    skew[1] /= scale[2]
    skew[2] /= scale[2]


    // At this point, the matrix (in rows) is orthonormal.
    // Check for a coordinate system flip.  If the determinant
    // is -1, then negate the matrix and the scaling factors.
    vec3.cross(pdum3, row[1], row[2])
    if (vec3.dot(row[0], pdum3) < 0) {
        for (var i = 0; i < 3; i++) {
            scale[i] *= -1;
            row[i][0] *= -1
            row[i][1] *= -1
            row[i][2] *= -1
        }
    }

    // Now, get the rotations out
    quaternion[0] = 0.5 * Math.sqrt(Math.max(1 + row[0][0] - row[1][1] - row[2][2], 0))
    quaternion[1] = 0.5 * Math.sqrt(Math.max(1 - row[0][0] + row[1][1] - row[2][2], 0))
    quaternion[2] = 0.5 * Math.sqrt(Math.max(1 - row[0][0] - row[1][1] + row[2][2], 0))
    quaternion[3] = 0.5 * Math.sqrt(Math.max(1 + row[0][0] + row[1][1] + row[2][2], 0))

    if (row[2][1] > row[1][2])
        quaternion[0] = -quaternion[0]
    if (row[0][2] > row[2][0])
        quaternion[1] = -quaternion[1]
    if (row[1][0] > row[0][1])
        quaternion[2] = -quaternion[2]
    return true
}
示例#5
0
文件: mesh.js 项目: gl-vis/gl-mesh3d
proto.drawTransparent = proto.draw = function(params) {
  params = params || {}
  var gl          = this.gl
  var model       = params.model      || IDENTITY
  var view        = params.view       || IDENTITY
  var projection  = params.projection || IDENTITY

  var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]]
  for(var i=0; i<3; ++i) {
    clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i])
    clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i])
  }

  var uniforms = {
    model:      model,
    view:       view,
    projection: projection,
    inverseModel: IDENTITY.slice(),

    clipBounds: clipBounds,

    kambient:   this.ambientLight,
    kdiffuse:   this.diffuseLight,
    kspecular:  this.specularLight,
    roughness:  this.roughness,
    fresnel:    this.fresnel,

    eyePosition:   [0,0,0],
    lightPosition: [0,0,0],

    contourColor: this.contourColor,

    texture:    0
  }

  uniforms.inverseModel = invert(uniforms.inverseModel, uniforms.model)

  gl.disable(gl.CULL_FACE)

  this.texture.bind(0)

  var invCameraMatrix = new Array(16)
  multiply(invCameraMatrix, uniforms.view, uniforms.model)
  multiply(invCameraMatrix, uniforms.projection, invCameraMatrix)
  invert(invCameraMatrix, invCameraMatrix)

  for(var i=0; i<3; ++i) {
    uniforms.eyePosition[i] = invCameraMatrix[12+i] / invCameraMatrix[15]
  }

  var w = invCameraMatrix[15]
  for(var i=0; i<3; ++i) {
    w += this.lightPosition[i] * invCameraMatrix[4*i+3]
  }
  for(var i=0; i<3; ++i) {
    var s = invCameraMatrix[12+i]
    for(var j=0; j<3; ++j) {
      s += invCameraMatrix[4*j+i] * this.lightPosition[j]
    }
    uniforms.lightPosition[i] = s / w
  }

  if(this.triangleCount > 0) {
    var shader = this.triShader
    shader.bind()
    shader.uniforms = uniforms

    this.triangleVAO.bind()
    gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3)
    this.triangleVAO.unbind()
  }

  if(this.edgeCount > 0 && this.lineWidth > 0) {
    var shader = this.lineShader
    shader.bind()
    shader.uniforms = uniforms

    this.edgeVAO.bind()
    gl.lineWidth(this.lineWidth * this.pixelRatio)
    gl.drawArrays(gl.LINES, 0, this.edgeCount*2)
    this.edgeVAO.unbind()
  }

  if(this.pointCount > 0) {
    var shader = this.pointShader
    shader.bind()
    shader.uniforms = uniforms

    this.pointVAO.bind()
    gl.drawArrays(gl.POINTS, 0, this.pointCount)
    this.pointVAO.unbind()
  }

  if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) {
    var shader = this.contourShader
    shader.bind()
    shader.uniforms = uniforms

    this.contourVAO.bind()
    gl.drawArrays(gl.LINES, 0, this.contourCount)
    this.contourVAO.unbind()
  }
}