New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ogl

Package Overview
Dependencies
Maintainers
1
Versions
127
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ogl - npm Package Compare versions

Comparing version 0.0.7 to 0.0.8

examples/performance.html

2

package.json
{
"name": "ogl",
"version": "0.0.7",
"version": "0.0.8",
"description": "WebGL Framework",

@@ -5,0 +5,0 @@ "main": "src",

@@ -35,3 +35,3 @@ <p align="center">

Use directly in your project with es6 modules and load directly in the browser - **no dev-stack required**.
[Download](https://github.com/oframe/ogl/archive/master.zip) and [load directly in the browser](https://developers.google.com/web/fundamentals/primers/modules) using es6 modules - **no dev-stack required**.

@@ -38,0 +38,0 @@ **or**

import {Transform} from './Transform.js';
import {Mat4} from '../math/Mat4.js';
import {Vec3} from '../math/Vec3.js';
// Used in unproject method
const tempMat4 = new Mat4();
const tempVec3a = new Vec3();
const tempVec3b = new Vec3();

@@ -28,2 +30,3 @@ export class Camera extends Transform {

this.viewMatrix = new Mat4();
this.projectionViewMatrix = new Mat4();

@@ -62,2 +65,5 @@ // Use orthographic if values set, else default to perspective camera

this.viewMatrix.inverse(this.worldMatrix);
// used for sorting
this.projectionViewMatrix.multiply(this.projectionMatrix, this.viewMatrix);
return this;

@@ -84,2 +90,45 @@ }

}
updateFrustum() {
if (!this.frustum) {
this.frustum = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
}
const m = this.projectionViewMatrix;
this.frustum[0].set(m[3] - m[0], m[7] - m[4], m[11] - m[8]).constant = m[15] - m[12]; // -x
this.frustum[1].set(m[3] + m[0], m[7] + m[4], m[11] + m[8]).constant = m[15] + m[12]; // +x
this.frustum[2].set(m[3] + m[1], m[7] + m[5], m[11] + m[9]).constant = m[15] + m[13]; // +y
this.frustum[3].set(m[3] - m[1], m[7] - m[5], m[11] - m[9]).constant = m[15] - m[13]; // -y
this.frustum[4].set(m[3] - m[2], m[7] - m[6], m[11] - m[10]).constant = m[15] - m[14]; // +z (far)
this.frustum[5].set(m[3] + m[2], m[7] + m[6], m[11] + m[10]).constant = m[15] + m[14]; // -z (near)
for (let i = 0; i < 6; i++) {
const invLen = 1.0 / this.frustum[i].length();
this.frustum[i].multiply(invLen);
this.frustum[i].constant *= invLen;
}
}
frustumIntersectsMesh(node) {
if (!node.geometry.bounds || node.geometry.bounds.radius === Infinity) node.geometry.computeBoundingSphere();
const center = tempVec3a;
center.copy(node.geometry.bounds.center);
center.applyMatrix4(node.worldMatrix);
const radius = node.geometry.bounds.radius * node.worldMatrix.getMaxScaleOnAxis();
return this.frustumIntersectsSphere(center, radius);
}
frustumIntersectsSphere(center, radius) {
const normal = tempVec3b;
for (let i = 0; i < 6; i++) {
const plane = this.frustum[i];
const distance = normal.copy(plane).dot(center) + plane.constant;
if (distance < -radius) return false;
}
return true;
}
}

@@ -18,2 +18,6 @@ // attribute params

import {Vec3} from '../math/Vec3.js';
const tempVec3 = new Vec3();
let ID = 0;

@@ -162,2 +166,61 @@

computeBoundingBox(array) {
// Use position buffer if available
if (!array && this.attributes.position) array = this.attributes.position.data;
if (!array) console.warn('No position buffer found to compute bounds');
if (!this.bounds) {
this.bounds = {
min: new Vec3(),
max: new Vec3(),
center: new Vec3(),
scale: new Vec3(),
radius: Infinity,
};
}
const min = this.bounds.min;
const max = this.bounds.max;
const center = this.bounds.center;
const scale = this.bounds.scale;
min.set(+Infinity);
max.set(-Infinity);
for (let i = 0, l = array.length; i < l; i += 3) {
const x = array[i];
const y = array[i + 1];
const z = array[i + 2];
min.x = Math.min(x, min.x);
min.y = Math.min(y, min.y);
min.z = Math.min(z, min.z);
max.x = Math.max(x, max.x);
max.y = Math.max(y, max.y);
max.z = Math.max(z, max.z);
}
scale.sub(max, min);
center.add(min, max).divide(2);
}
computeBoundingSphere(array) {
// Use position buffer if available
if (!array && this.attributes.position) array = this.attributes.position.data;
if (!array) console.warn('No position buffer found to compute bounds');
if (!this.bounds) this.computeBoundingBox(array);
let maxRadiusSq = 0;
for (let i = 0, l = array.length; i < l; i += 3) {
tempVec3.fromArray(array, i);
maxRadiusSq = Math.max(maxRadiusSq, this.bounds.center.squaredDistance(tempVec3));
}
this.bounds.radius = Math.sqrt(maxRadiusSq);
}
remove() {

@@ -164,0 +227,0 @@ if (this.vao) this.gl.renderer.deleteVertexArray(this.vao);

import {Transform} from './Transform.js';
import {Mat3} from '../math/Mat3.js';
import {Mat4} from '../math/Mat4.js';
import {Vec3} from '../math/Vec3.js';
const tempVec3 = new Vec3();
let ID = 0;

@@ -13,5 +12,8 @@ export class Mesh extends Transform {

mode = gl.TRIANGLES,
frustumCulled = true,
renderOrder = 0,
} = {}) {
super(gl);
this.gl = gl;
this.id = ID++;

@@ -22,2 +24,8 @@ this.geometry = geometry;

// Used to skip frustum culling
this.frustumCulled = frustumCulled;
// Override sorting to force an order
this.renderOrder = renderOrder;
this.modelViewMatrix = new Mat4();

@@ -40,4 +48,4 @@ this.normalMatrix = new Mat3();

draw({
camera,
} = {}) {
camera,
} = {}) {
this.onBeforeRender && this.onBeforeRender({mesh: this, camera});

@@ -71,64 +79,2 @@

}
computeBoundingBox(array) {
// Use position buffer if available
if (!array && this.geometry.attributes.position) array = this.geometry.attributes.position.data;
if (!array) console.warn('No position buffer found to compute bounds');
if (!this.bounds) {
this.bounds = {
min: new Vec3(),
max: new Vec3(),
center: new Vec3(),
scale: new Vec3(),
radius: Infinity,
};
}
const min = this.bounds.min;
const max = this.bounds.max;
const center = this.bounds.center;
const scale = this.bounds.scale;
min.set(+Infinity);
max.set(-Infinity);
for (let i = 0, l = array.length; i < l; i += 3) {
const x = array[i];
const y = array[i + 1];
const z = array[i + 2];
min.x = Math.min(x, min.x);
min.y = Math.min(y, min.y);
min.z = Math.min(z, min.z);
max.x = Math.max(x, max.x);
max.y = Math.max(y, max.y);
max.z = Math.max(z, max.z);
}
scale.sub(max, min);
center.add(min, max).divide(2);
// This is not an accurate radius - use computeBoundingSphere if accuracy needed
this.bounds.radius = tempVec3.copy(scale).divide(2).length();
}
computeBoundingSphere(array) {
// Use position buffer if available
if (!array && this.geometry.attributes.position) array = this.geometry.attributes.position.data;
if (!array) console.warn('No position buffer found to compute bounds');
if (!this.bounds) this.computeBoundingBox(array);
let maxRadiusSq = 0;
for (let i = 0, l = array.length; i < l; i += 3) {
tempVec3.fromArray(array, i);
maxRadiusSq = Math.max(maxRadiusSq, this.bounds.center.squaredDistance(tempVec3));
}
this.bounds.radius = Math.sqrt(maxRadiusSq);
}
}

@@ -51,3 +51,3 @@ // TODO: upload empty texture if null ? maybe not

if (gl.getShaderInfoLog(vertexShader) !== '') {
console.warn(`${gl.getShaderInfoLog(vertexShader)}\nVertex Shader\n${addLineNumbers(vertexShader)}`);
console.warn(`${gl.getShaderInfoLog(vertexShader)}\nVertex Shader\n${addLineNumbers(vertex)}`);
}

@@ -60,3 +60,3 @@

if (gl.getShaderInfoLog(fragmentShader) !== '') {
console.warn(`${gl.getShaderInfoLog(fragmentShader)}\nFragment Shader\n${addLineNumbers(fragmentShader)}`);
console.warn(`${gl.getShaderInfoLog(fragmentShader)}\nFragment Shader\n${addLineNumbers(fragment)}`);
}

@@ -63,0 +63,0 @@

import {Mat4} from '../math/Mat4.js';
import {Vec3} from '../math/Vec3.js';
// TODO: support frustum culling ?
// TODO: Handle context loss https://www.khronos.org/webgl/wiki/HandlingContextLost
// TODO: extend sorting to be more customisable
// sort into 3 groups:
// - opaque (depthTest: true, depthWrite: true)
// - then sort by program
// - then sort by z-depth (front to back)
// - then sort by texture
// - transparent (depthTest: true, depthWrite: false)
// - ui (depthTest: false, depthWrite: false)

@@ -23,3 +15,2 @@ // Not automatic - devs to use these methods manually

const projMat4 = new Mat4();
const tempVec3 = new Vec3();

@@ -41,3 +32,2 @@

autoClear = true,
sort = true,
} = {}) {

@@ -52,3 +42,2 @@ const attributes = {alpha, depth, stencil, antialias, premultipliedAlpha, preserveDrawingBuffer, powerPreference};

this.autoClear = autoClear;
this.sort = sort;

@@ -219,55 +208,76 @@ // Attempt WebGL2, otherwise fallback to WebGL1

drawOpaque(scene, camera) {
const opaque = [];
scene.traverse(node => {
if (!node.program || node.program.transparent) return;
opaque.splice(getRenderOrder(node), 0, node);
});
function getRenderOrder(node) {
node.worldMatrix.getTranslation(tempVec3);
tempVec3.applyMatrix4(projMat4);
node.zDepth = tempVec3.z;
for (let i = 0; i < opaque.length; i++) {
if (node.zDepth <= opaque[i].zDepth) return i;
}
return opaque.length;
sortOpaque(a, b) {
if (a.renderOrder !== b.renderOrder) {
return a.renderOrder - b.renderOrder;
} else if (a.program.id !== b.program.id) {
return a.program.id - b.program.id;
} else if (a.zDepth !== b.zDepth) {
return a.zDepth - b.zDepth;
} else {
return b.id - a.id;
}
}
for (let i = 0; i < opaque.length; i++) {
opaque[i].draw({camera});
sortTransparent(a, b) {
if (a.renderOrder !== b.renderOrder) {
return a.renderOrder - b.renderOrder;
} if (a.zDepth !== b.zDepth) {
return b.zDepth - a.zDepth;
} else {
return b.id - a.id;
}
}
drawTransparent(scene, camera) {
const transparent = [];
const custom = [];
getRenderList({scene, camera, frustumCull, sort}) {
let renderList = [];
if (camera && frustumCull) camera.updateFrustum();
// Get visible
scene.traverse(node => {
if (!node.program || !node.program.transparent) return;
if (!node.visible) return true;
if (!node.draw) return;
// If manual order set, add to queue last
if (node.renderOrder !== undefined) return custom.push(node);
transparent.splice(getRenderOrder(node), 0, node);
if (frustumCull && node.frustumCulled && camera) {
if (!camera.frustumIntersectsMesh(node)) return;
}
renderList.push(node);
});
function getRenderOrder(node) {
node.worldMatrix.getTranslation(tempVec3);
tempVec3.applyMatrix4(projMat4);
if (sort) {
const opaque = [];
const transparent = []; // depthTest true
const ui = []; // depthTest false
node.zDepth = tempVec3.z;
for (let i = 0; i < transparent.length; i++) {
if (node.zDepth >= transparent[i].zDepth) return i;
}
return transparent.length;
}
renderList.forEach(node => {
// Add manually ordered nodes
for (let i = 0; i < custom.length; i++) {
transparent.splice(custom[i].renderOrder, 0, custom[i]);
// Split into the 3 render groups
if (!node.program.transparent) {
opaque.push(node);
} else if (node.program.depthTest) {
transparent.push(node);
} else {
ui.push(node);
}
node.zDepth = 0;
// Only calculate z-depth if renderOrder unset and depthTest is true
if (node.renderOrder !== 0 || !node.program.depthTest || !camera) return;
// update z-depth
node.worldMatrix.getTranslation(tempVec3);
tempVec3.applyMatrix4(camera.projectionViewMatrix);
node.zDepth = tempVec3.z;
});
opaque.sort(this.sortOpaque);
transparent.sort(this.sortTransparent);
ui.sort(this.sortTransparent);
renderList = opaque.concat(transparent, ui);
}
for (let i = 0; i < transparent.length; i++) {
transparent[i].draw({camera});
}
return renderList;
}

@@ -280,2 +290,4 @@

update = true,
sort = true,
frustumCull = true,
}) {

@@ -311,14 +323,9 @@

// can only sort if camera available
if (this.sort && camera) {
projMat4.multiply(camera.projectionMatrix, camera.viewMatrix);
this.drawOpaque(scene, camera);
this.drawTransparent(scene, camera);
} else {
scene.traverse(node => {
if (!node.draw) return;
node.draw({camera});
});
}
// Get render list - entails culling and sorting
const renderList = this.getRenderList({scene, camera, frustumCull, sort});
renderList.forEach(node => {
node.draw({camera});
});
}
}

@@ -10,2 +10,3 @@ import {Vec3} from '../math/Vec3.js';

this.children = [];
this.visible = true;

@@ -26,16 +27,16 @@ this.matrix = new Mat4();

setParent(parent, notifyChild = true) {
if (!parent && notifyChild) this.parent.removeChild(this, false);
setParent(parent, notifyParent = true) {
if (notifyParent && this.parent && parent !== this.parent) this.parent.removeChild(this, false);
this.parent = parent;
if (parent && notifyChild) parent.addChild(this, false);
if (notifyParent && parent) parent.addChild(this, false);
}
addChild(child, notifyParent = true) {
addChild(child, notifyChild = true) {
if (!~this.children.indexOf(child)) this.children.push(child);
if (notifyParent) child.setParent(this, false);
if (notifyChild) child.setParent(this, false);
}
removeChild(child, notifyParent = true) {
removeChild(child, notifyChild = true) {
if (!!~this.children.indexOf(child)) this.children.splice(this.children.indexOf(child), 1);
if (notifyParent) child.setParent(null, false);
if (notifyChild) child.setParent(null, false);
}

@@ -64,3 +65,5 @@

traverse(callback) {
callback(this);
// Return true in callback to stop traversing children
if (callback(this)) return;
for (let i = 0, l = this.children.length; i < l; i ++) {

@@ -67,0 +70,0 @@ this.children[i].traverse(callback);

@@ -42,10 +42,7 @@ // TODO: test orthographic

meshes.forEach(mesh => {
if (!mesh.bounds) {
if (mesh.raycast === 'sphere') {
mesh.computeBoundingSphere();
} else {
mesh.computeBoundingBox();
}
}
// Create bounds
if (!mesh.geometry.bounds) mesh.geometry.computeBoundingBox();
if (mesh.geometry.raycast === 'sphere' && mesh.geometry.bounds === Infinity) mesh.geometry.computeBoundingSphere();
// Take world space ray and make it object space to align with bounding box

@@ -57,6 +54,6 @@ invWorldMat4.inverse(mesh.worldMatrix);

let distance = 0;
if (mesh.raycast === 'sphere') {
distance = this.intersectSphere(mesh.bounds, origin, direction);
if (mesh.geometry.raycast === 'sphere') {
distance = this.intersectSphere(mesh.geometry.bounds, origin, direction);
} else {
distance = this.intersectBox(mesh.bounds, origin, direction);
distance = this.intersectBox(mesh.geometry.bounds, origin, direction);
}

@@ -98,3 +95,3 @@ if (!distance) return;

// AABB - Axis aligned bounding box testing
// Ray AABB - Ray Axis aligned bounding box testing
intersectBox(box, origin = this.origin, direction = this.direction) {

@@ -118,4 +115,4 @@ let tmin, tmax, tYmin, tYmax, tZmin, tZmax;

if ( tYmin > tmin || tmin !== tmin ) tmin = tYmin;
if ( tYmax < tmax || tmax !== tmax ) tmax = tYmax;
if (tYmin > tmin) tmin = tYmin;
if (tYmax < tmax) tmax = tYmax;

@@ -126,4 +123,4 @@ tZmin = ((invdirz >= 0 ? min.z : max.z) - origin.z) * invdirz;

if ((tmin > tZmax) || (tZmin > tmax)) return 0;
if (tZmin > tmin || tmin !== tmin) tmin = tZmin;
if (tZmax < tmax || tmax !== tmax) tmax = tZmax;
if (tZmin > tmin) tmin = tZmin;
if (tZmax < tmax) tmax = tZmax;

@@ -130,0 +127,0 @@ if (tmax < 0) return 0;

@@ -920,2 +920,20 @@ const EPSILON = 0.000001;

export function getMaxScaleOnAxis(mat) {
let m11 = mat[0];
let m12 = mat[1];
let m13 = mat[2];
let m21 = mat[4];
let m22 = mat[5];
let m23 = mat[6];
let m31 = mat[8];
let m32 = mat[9];
let m33 = mat[10];
const x = m11 * m11 + m12 * m12 + m13 * m13;
const y = m21 * m21 + m22 * m22 + m23 * m23;
const z = m31 * m31 + m32 * m32 + m33 * m33;
return Math.sqrt(Math.max(x, y, z));
}
/**

@@ -922,0 +940,0 @@ * Returns a quaternion representing the rotational component

@@ -140,2 +140,6 @@ import * as Mat4Func from './functions/Mat4Func.js';

getMaxScaleOnAxis() {
return Mat4Func.getMaxScaleOnAxis(this);
}
lookAt(eye, target, up) {

@@ -142,0 +146,0 @@ Mat4Func.targetTo(this, eye, target, up);

@@ -47,2 +47,7 @@ import * as Vec4Func from './functions/Vec4Func.js';

normalize() {
Vec4Func.normalize(this, this);
return this;
}
fromArray(a, o = 0) {

@@ -49,0 +54,0 @@ this[0] = a[o];

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc