wip(type): update entry.

This commit is contained in:
pissang 2022-04-30 13:56:33 +08:00
parent 230d95683b
commit ae01fe6770
44 changed files with 621 additions and 568 deletions

View File

@ -1,151 +1,156 @@
var glob = require('glob');
var fs = require('fs');
var path = require('path');
console.log('Deprecated.');
// var glob = require('glob');
// var fs = require('fs');
// var path = require('path');
var ROOT = __dirname + '/../';
var SRC_ROOT = ROOT + 'src/';
var TS_ROOT = ROOT + 'typescript/';
var TS_PORTAL = 'index.d.ts';
// var ROOT = __dirname + '/../';
// var SRC_ROOT = ROOT + 'src/';
// var TS_ROOT = ROOT + 'typescript/';
// var TS_PORTAL = 'index.d.ts';
var OUTPUT_PORTAL = 'claygl.ts';
// var OUTPUT_PORTAL = 'claygl.ts';
var template = fs.readFileSync(__dirname + '/claygl_template.tpl', 'utf-8');
// var template = fs.readFileSync(__dirname + '/claygl_template.tpl', 'utf-8');
var idx = 0;
var blacklist = ['shader/builtin', 'app/', 'canvas/', 'gpu/', 'glmatrix/'];
// var blacklist = ['shader/builtin', 'app/', 'canvas/', 'gpu/', 'glmatrix/'];
var topLevelClasses = [
'math/BoundingBox',
'math/Frustum',
'math/Matrix2',
'math/Matrix2d',
'math/Matrix3',
'math/Matrix4',
'math/Plane',
'math/Quaternion',
'math/Ray',
'math/Value',
'math/Vector2',
'math/Vector3',
'math/Vector4'
];
// var topLevelClasses = [
// 'math/BoundingBox',
// 'math/Frustum',
// 'math/Matrix2',
// 'math/Matrix2d',
// 'math/Matrix3',
// 'math/Matrix4',
// 'math/Plane',
// 'math/Quaternion',
// 'math/Ray',
// 'math/Value',
// 'math/Vector2',
// 'math/Vector3',
// 'math/Vector4'
// ];
glob(
'**/*.ts',
{
cwd: SRC_ROOT
},
function (err, files) {
var namespace = {};
// glob(
// '**/*.ts',
// {
// cwd: SRC_ROOT
// },
// function (err, files) {
// var namespace = {};
// var tsReferenceList = [];
// var basenameCount = {};
files.forEach(function (file) {
var filePathWithOutExt = file.slice(0, -3);
if (
file.match(/claygl.*?\.ts/) ||
file.indexOf('_') >= 0 ||
file.endsWith('.glsl.ts') ||
blacklist.find(function (item) {
return filePathWithOutExt.indexOf(item) >= 0;
})
) {
return;
}
// files.forEach(function (file) {
// var filePathWithOutExt = file.slice(0, -3);
// if (
// file.match(/claygl.*?\.ts/) ||
// file.indexOf('_') >= 0 ||
// file.endsWith('.glsl.ts') ||
// blacklist.find(function (item) {
// return filePathWithOutExt.indexOf(item) >= 0;
// })
// ) {
// return;
// }
var pathArray = filePathWithOutExt.split('/');
var baseName = pathArray.pop() + '$' + idx++;
// var pathArray = filePathWithOutExt.split('/');
// var baseName = pathArray.pop();
// basenameCount[baseName] = basenameCount[baseName] || 0;
// if (baseName > 0) {
// baseName = baseName + basenameCount[baseName];
// }
// basenameCount[baseName]++;
var object = pathArray.reduce(function (memo, propName) {
if (!memo[propName]) {
memo[propName] = {};
}
return memo[propName];
}, namespace);
// var object = pathArray.reduce(function (memo, propName) {
// if (!memo[propName]) {
// memo[propName] = {};
// }
// return memo[propName];
// }, namespace);
object[baseName] = `import ${baseName} from './${filePathWithOutExt}';`;
// object[baseName] = `import ${baseName} from './${filePathWithOutExt}';`;
// var tsPath = TS_ROOT + filePathWithOutExt + '.d.ts';
// // var tsPath = TS_ROOT + filePathWithOutExt + '.d.ts';
// if (fs.existsSync(tsPath)) {
// tsReferenceList.push(filePathWithOutExt);
// }
});
// // if (fs.existsSync(tsPath)) {
// // tsReferenceList.push(filePathWithOutExt);
// // }
// });
var exportCode = exportPkg(namespace);
var output = template.replace(/\{\{\$exportsObject\}\}/, exportCode);
// var exportCode = exportPkg(namespace);
// var output = template.replace(/\{\{\$exportsObject\}\}/, exportCode);
fs.writeFileSync(SRC_ROOT + OUTPUT_PORTAL, output, 'utf-8');
// fs.writeFileSync(SRC_ROOT + OUTPUT_PORTAL, output, 'utf-8');
// Write to ts reference file
// var referenceCode = tsReferenceList.map(function(path) {
// return '///<reference path="typescript/' + path + '" />';
// }).join('\n');
// fs.writeFileSync(ROOT + TS_PORTAL, referenceCode, 'utf-8');
}
);
// // Write to ts reference file
// // var referenceCode = tsReferenceList.map(function(path) {
// // return '///<reference path="typescript/' + path + '" />';
// // }).join('\n');
// // fs.writeFileSync(ROOT + TS_PORTAL, referenceCode, 'utf-8');
// }
// );
/**
* Export pkg to import/export codes
* @param {Object} pkg package to export
* @param {Boolean} isChild if it is a child package
* @param {String} pkgName name of the package, if it's a child
* @param {String[]} externImports imports
*/
function exportPkg(pkg, isChild, pkgName, externImports) {
var keys = Object.keys(pkg);
var imports = externImports || [];
// /**
// * Export pkg to import/export codes
// * @param {Object} pkg package to export
// * @param {Boolean} isChild if it is a child package
// * @param {String} pkgName name of the package, if it's a child
// * @param {String[]} externImports imports
// */
// function exportPkg(pkg, isChild, pkgName, externImports) {
// var keys = Object.keys(pkg);
// var imports = externImports || [];
var topLevels = [];
var children = keys.map(function (name) {
if (isString(pkg[name])) {
var className = name.substring(0, name.indexOf('$'));
if (
topLevelClasses.find(function (item) {
return pkg[name].indexOf(item) >= 0;
})
) {
topLevels.push(name);
}
// a class, not a packagge
imports.push(pkg[name]);
if (pkgName) {
// export as a child class in package
// indentation + (key : value)
return (isChild ? ' ' : ' ') + className + ': ' + name;
} else {
// export as a class at root level
return `export { ${name} as ${className} };`;
}
} else {
// export as a child package
return exportPkg(pkg[name], pkgName && true, name, imports);
}
});
// var topLevels = [];
// var children = keys.map(function (name) {
// if (isString(pkg[name])) {
// var className = name;
// if (
// topLevelClasses.find(function (item) {
// return pkg[name].indexOf(item) >= 0;
// })
// ) {
// topLevels.push(name);
// }
// // a class, not a packagge
// imports.push(pkg[name]);
// if (pkgName) {
// // export as a child class in package
// // indentation + (key : value)
// return (isChild ? ' ' : ' ') + className + ': ' + name;
// } else {
// // export as a class at root level
// return `export { ${name} as ${className} };`;
// }
// } else {
// // export as a child package
// return exportPkg(pkg[name], pkgName && true, name, imports);
// }
// });
var importCode = externImports ? '' : imports.join('\n') + '\n\n';
var exportCode;
if (pkgName) {
if (isChild) {
// export as a grand-child package
exportCode = ` ${pkgName}: {\n${children.join(',\n')}\n }`;
} else {
// export as a package at root level
exportCode = `\nconst ${pkgName} = {\n${children.join(',\n')}\n};\nexport { ${pkgName} };\n`;
}
} else {
// export child classes
exportCode = children.join('\n');
}
// var importCode = externImports ? '' : imports.join('\n') + '\n\n';
// var exportCode;
// if (pkgName) {
// if (isChild) {
// // export as a grand-child package
// exportCode = ` ${pkgName}: {\n${children.join(',\n')}\n }`;
// } else {
// // export as a package at root level
// exportCode = `\nconst ${pkgName} = {\n${children.join(',\n')}\n};\nexport { ${pkgName} };\n`;
// }
// } else {
// // export child classes
// exportCode = children.join('\n');
// }
topLevels.forEach(function (name) {
var className = name.substring(0, name.indexOf('$'));
exportCode += `export { ${name} as ${className} };\n`;
});
// topLevels.forEach(function (name) {
// var className = name.substring(0, name.indexOf('$'));
// exportCode += `export { ${name} as ${className} };\n`;
// });
return importCode + exportCode;
}
// return importCode + exportCode;
// }
function isString(s) {
return typeof s === 'string';
}
// function isString(s) {
// return typeof s === 'string';
// }

View File

@ -50,7 +50,8 @@
"mocha": "^4.0.1",
"remap-istanbul": "^0.9.5",
"rollup": "^2.70.2",
"terser": "^5.12.1"
"terser": "^5.12.1",
"typescript": "^4.6.4"
},
"dependencies": {
"@rollup/plugin-typescript": "^8.3.2",

52
pnpm-lock.yaml generated
View File

@ -16,14 +16,15 @@ specifiers:
rollup: ^2.70.2
terser: ^5.12.1
tslib: ^2.3.1
typescript: ^4.6.4
dependencies:
'@rollup/plugin-typescript': 8.3.2_rollup@2.70.2+tslib@2.3.1
'@rollup/plugin-typescript': 8.3.2_4a24bde9c77b6cb2b1da67564afd9101
tslib: 2.3.1
devDependencies:
'@typescript-eslint/eslint-plugin': 5.20.0_659090a1a2f507e2e971a348ed10736d
'@typescript-eslint/parser': 5.20.0_eslint@8.13.0
'@typescript-eslint/eslint-plugin': 5.20.0_bd994e352ae473ad3e507fadfa78fd8c
'@typescript-eslint/parser': 5.20.0_eslint@8.13.0+typescript@4.6.4
electron: 1.7.9
electron-mocha: 4.0.3
eslint: 8.13.0
@ -35,6 +36,7 @@ devDependencies:
remap-istanbul: 0.9.6
rollup: 2.70.2
terser: 5.12.1
typescript: 4.6.4
packages:
@ -91,7 +93,7 @@ packages:
fastq: 1.13.0
dev: true
/@rollup/plugin-typescript/8.3.2_rollup@2.70.2+tslib@2.3.1:
/@rollup/plugin-typescript/8.3.2_4a24bde9c77b6cb2b1da67564afd9101:
resolution: {integrity: sha512-MtgyR5LNHZr3GyN0tM7gNO9D0CS+Y+vflS4v/PHmrX17JCkHUYKvQ5jN5o3cz1YKllM3duXUqu3yOHwMPUxhDg==}
engines: {node: '>=8.0.0'}
peerDependencies:
@ -103,6 +105,7 @@ packages:
resolve: 1.22.0
rollup: 2.70.2
tslib: 2.3.1
typescript: 4.6.4
dev: false
/@rollup/pluginutils/3.1.0_rollup@2.70.2:
@ -129,7 +132,7 @@ packages:
resolution: {integrity: sha512-29GS75BE8asnTno3yB6ubOJOO0FboExEqNJy4bpz0GSmW/8wPTNL4h9h63c6s1uTrOopCmJYe/4yJLh5r92ZUA==}
dev: true
/@typescript-eslint/eslint-plugin/5.20.0_659090a1a2f507e2e971a348ed10736d:
/@typescript-eslint/eslint-plugin/5.20.0_bd994e352ae473ad3e507fadfa78fd8c:
resolution: {integrity: sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -140,22 +143,23 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': 5.20.0_eslint@8.13.0
'@typescript-eslint/parser': 5.20.0_eslint@8.13.0+typescript@4.6.4
'@typescript-eslint/scope-manager': 5.20.0
'@typescript-eslint/type-utils': 5.20.0_eslint@8.13.0
'@typescript-eslint/utils': 5.20.0_eslint@8.13.0
'@typescript-eslint/type-utils': 5.20.0_eslint@8.13.0+typescript@4.6.4
'@typescript-eslint/utils': 5.20.0_eslint@8.13.0+typescript@4.6.4
debug: 4.3.4
eslint: 8.13.0
functional-red-black-tree: 1.0.1
ignore: 5.2.0
regexpp: 3.2.0
semver: 7.3.7
tsutils: 3.21.0
tsutils: 3.21.0_typescript@4.6.4
typescript: 4.6.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/parser/5.20.0_eslint@8.13.0:
/@typescript-eslint/parser/5.20.0_eslint@8.13.0+typescript@4.6.4:
resolution: {integrity: sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -167,9 +171,10 @@ packages:
dependencies:
'@typescript-eslint/scope-manager': 5.20.0
'@typescript-eslint/types': 5.20.0
'@typescript-eslint/typescript-estree': 5.20.0
'@typescript-eslint/typescript-estree': 5.20.0_typescript@4.6.4
debug: 4.3.4
eslint: 8.13.0
typescript: 4.6.4
transitivePeerDependencies:
- supports-color
dev: true
@ -182,7 +187,7 @@ packages:
'@typescript-eslint/visitor-keys': 5.20.0
dev: true
/@typescript-eslint/type-utils/5.20.0_eslint@8.13.0:
/@typescript-eslint/type-utils/5.20.0_eslint@8.13.0+typescript@4.6.4:
resolution: {integrity: sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -192,10 +197,11 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/utils': 5.20.0_eslint@8.13.0
'@typescript-eslint/utils': 5.20.0_eslint@8.13.0+typescript@4.6.4
debug: 4.3.4
eslint: 8.13.0
tsutils: 3.21.0
tsutils: 3.21.0_typescript@4.6.4
typescript: 4.6.4
transitivePeerDependencies:
- supports-color
dev: true
@ -205,7 +211,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/typescript-estree/5.20.0:
/@typescript-eslint/typescript-estree/5.20.0_typescript@4.6.4:
resolution: {integrity: sha512-36xLjP/+bXusLMrT9fMMYy1KJAGgHhlER2TqpUVDYUQg4w0q/NW/sg4UGAgVwAqb8V4zYg43KMUpM8vV2lve6w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -220,12 +226,13 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.3.7
tsutils: 3.21.0
tsutils: 3.21.0_typescript@4.6.4
typescript: 4.6.4
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/utils/5.20.0_eslint@8.13.0:
/@typescript-eslint/utils/5.20.0_eslint@8.13.0+typescript@4.6.4:
resolution: {integrity: sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@ -234,7 +241,7 @@ packages:
'@types/json-schema': 7.0.11
'@typescript-eslint/scope-manager': 5.20.0
'@typescript-eslint/types': 5.20.0
'@typescript-eslint/typescript-estree': 5.20.0
'@typescript-eslint/typescript-estree': 5.20.0_typescript@4.6.4
eslint: 8.13.0
eslint-scope: 5.1.1
eslint-utils: 3.0.0_eslint@8.13.0
@ -2663,13 +2670,14 @@ packages:
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
dev: false
/tsutils/3.21.0:
/tsutils/3.21.0_typescript@4.6.4:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
dependencies:
tslib: 1.14.1
typescript: 4.6.4
dev: true
/tunnel-agent/0.6.0:
@ -2705,6 +2713,12 @@ packages:
resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=}
dev: true
/typescript/4.6.4:
resolution: {integrity: sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==}
engines: {node: '>=4.2.0'}
hasBin: true
dev: true
/uglify-js/3.15.4:
resolution: {integrity: sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==}
engines: {node: '>=0.8.0'}

View File

@ -5,7 +5,7 @@ import Ray from './math/Ray';
import * as vec4 from './glmatrix/vec4';
import * as vec3 from './glmatrix/vec3';
import { Vector2 } from './claygl';
import Vector2 from './math/Vector2';
export interface CameraOpts extends ClayNodeOpts {}
@ -31,12 +31,6 @@ class Camera extends ClayNode {
*/
frustum = new Frustum();
constructor(opts: Partial<ClayNodeOpts>) {
opts = opts || {};
super(opts);
this.update();
}
update() {
super.update.call(this);
Matrix4.invert(this.viewMatrix, this.worldTransform);

View File

@ -49,10 +49,9 @@ class InstancedMesh extends Mesh {
private _attributesSymbols: string[] = [];
constructor(opts?: Partial<InstancedMeshOpts>) {
opts = opts || {};
super(opts);
this.instances = optional(opts.instances, []);
this.instances = optional(opts && opts.instances, []);
this.createInstancedAttribute('instanceMat1', 'float', 4, 1);
this.createInstancedAttribute('instanceMat2', 'float', 4, 1);
this.createInstancedAttribute('instanceMat3', 'float', 4, 1);

View File

@ -1,4 +1,3 @@
import Base from './core/Base';
import { optional } from './core/util';
import type ClayNode from './Node';

View File

@ -56,7 +56,6 @@ class Light extends ClayNode {
>;
constructor(opts?: Partial<LightOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
}

View File

@ -24,8 +24,8 @@ class Mesh extends Renderable {
offsetMatrix?: Matrix4;
constructor(opts?: Partial<MeshOpts>) {
opts = opts || {};
super(opts);
opts = opts || {};
if (opts.skeleton) {
this.skeleton = opts.skeleton;
}

View File

@ -89,7 +89,7 @@ class ClayNode extends Notifier {
/**
* The root scene mounted. Null if it is a isolated node
*/
protected _scene: Scene;
protected _scene?: Scene;
private _inIterating = false;
@ -135,12 +135,6 @@ class ClayNode extends Notifier {
* @param {string} name
*/
setName(name: string) {
const scene = this._scene;
if (scene) {
const nodeRepository = scene._nodeRepository;
delete nodeRepository[this.name];
nodeRepository[name] = this;
}
this.name = name;
}
@ -194,7 +188,7 @@ class ClayNode extends Notifier {
children[idx]._parent = undefined;
if (this._scene) {
children[idx].traverse(this._removeSelfFromScene, this);
children[idx].traverse((child) => this._removeSelfFromScene(child));
}
}
@ -218,12 +212,12 @@ class ClayNode extends Notifier {
}
_removeSelfFromScene(descendant: ClayNode) {
descendant._scene.removeFromScene(descendant);
descendant._scene = null;
descendant._scene!.removeFromScene(descendant);
descendant._scene = undefined;
}
_addSelfToScene(descendant: ClayNode) {
this._scene.addToScene(descendant);
this._scene!.addToScene(descendant);
descendant._scene = this._scene;
}
@ -508,7 +502,7 @@ class ClayNode extends Notifier {
* @return {clay.BoundingBox}
*/
// TODO Skinning
getBoundingBox(filter: GetBoundingBoxFilter, out?: BoundingBox): BoundingBox {
getBoundingBox(filter?: GetBoundingBoxFilter, out?: BoundingBox): BoundingBox {
out = out || new BoundingBox();
filter = filter || defaultBoundingBoxNodeFilter;
const invWorldTransform = tmpMat4;
@ -521,7 +515,7 @@ class ClayNode extends Notifier {
this.traverse(function (mesh) {
const geo = (mesh as Mesh).geometry;
if (geo && geo.boundingBox && filter(mesh)) {
if (geo && geo.boundingBox && filter(mesh as Mesh)) {
tmpBBox.copy(geo.boundingBox);
Matrix4.multiply(tmpMat4, invWorldTransform, mesh.worldTransform);
tmpBBox.applyTransform(tmpMat4);

View File

@ -106,8 +106,8 @@ class Renderable extends ClayNode {
__depth = 0;
constructor(opts?: Partial<RenderableOpts>) {
opts = opts || {};
super(opts);
opts = opts || {};
for (let i = 0; i < properties.length; i++) {
const name = properties[i];

View File

@ -330,8 +330,8 @@ class Renderer extends Notifier {
private _programMgr: ProgramManager;
constructor(opts?: Partial<RendererOpts>) {
opts = opts || {};
super();
opts = opts || {};
const canvas = (this.canvas = opts.canvas || vendor.createCanvas());
try {

View File

@ -40,7 +40,11 @@ function getProgramKey(lightNumbers: Record<string, number>) {
return id;
}
function setUniforms(uniforms: Record<string, ShaderUniform>, program, renderer: Renderer) {
function setUniforms(
uniforms: Record<string, ShaderUniform>,
program: GLProgram,
renderer: Renderer
) {
for (const symbol in uniforms) {
const lu = uniforms[symbol];
if (lu.type === 'tv') {
@ -135,10 +139,9 @@ class Scene extends ClayNode {
private _renderLists = new LRUCache<RenderList>(20);
constructor(opts?: Partial<SceneOpts>) {
opts = opts || {};
super(opts);
this.material = opts.material;
this.material = opts && opts.material;
this._scene = this;
}

View File

@ -8,8 +8,8 @@ import * as mat4 from './glmatrix/mat4';
import * as vec3 from './glmatrix/vec3';
import * as quat from './glmatrix/quat';
import type ClayNode from './Node';
import type SkinningClip from './animation/SkinningClip';
import type Geometry from './Geometry';
import TrackAnimator from './animation/TrackAnimator';
const tmpBoundingBox = new BoundingBox();
const tmpMat4 = new Matrix4();
@ -40,9 +40,9 @@ class Skeleton {
*/
boundingBox?: BoundingBox;
private _clips: {
private _animations: {
maps: number[];
clip: SkinningClip;
animator: TrackAnimator;
}[] = [];
// Matrix to joint space (relative to root joint)
@ -70,13 +70,13 @@ class Skeleton {
/**
* Add a skinning clip and create a map between clip and skeleton
* @param clip
* @param animator
* @param mapRule Map between joint name in skeleton and joint name in clip
*/
addClip(clip: SkinningClip, mapRule?: Record<string, string>) {
addAnimator(animator: TrackAnimator, mapRule?: Record<string, string>) {
// Clip have been exists in
for (let i = 0; i < this._clips.length; i++) {
if (this._clips[i].clip === clip) {
for (let i = 0; i < this._animations.length; i++) {
if (this._animations[i].animator === animator) {
return;
}
}
@ -86,10 +86,10 @@ class Skeleton {
maps[i] = -1;
}
// Create avatar
for (let i = 0; i < clip.tracks.length; i++) {
for (let i = 0; i < animator.tracks.length; i++) {
for (let j = 0; j < this.joints.length; j++) {
const joint = this.joints[j];
const track = clip.tracks[i];
const track = animator.tracks[i];
let jointName = joint.name;
if (mapRule) {
jointName = mapRule[jointName];
@ -101,51 +101,51 @@ class Skeleton {
}
}
this._clips.push({
this._animations.push({
maps: maps,
clip: clip
animator: animator
});
return this._clips.length - 1;
return this._animations.length - 1;
}
/**
* @param clip
* @param animator
*/
removeClip(clip: SkinningClip) {
removeAnimator(animator: TrackAnimator) {
let idx = -1;
for (let i = 0; i < this._clips.length; i++) {
if (this._clips[i].clip === clip) {
for (let i = 0; i < this._animations.length; i++) {
if (this._animations[i].animator === animator) {
idx = i;
break;
}
}
if (idx > 0) {
this._clips.splice(idx, 1);
this._animations.splice(idx, 1);
}
}
/**
* Remove all clips
*/
removeClipsAll() {
this._clips = [];
removeAnimatorsAll() {
this._animations = [];
}
/**
* Get clip by index
* Get animator by index
* @param index
*/
getClip(index: number) {
if (this._clips[index]) {
return this._clips[index].clip;
getAnimator(index: number) {
if (this._animations[index]) {
return this._animations[index].animator;
}
}
/**
* Return clips number
*/
getClipsCount() {
return this._clips.length;
getAnimatorsCount() {
return this._animations.length;
}
/**
@ -338,16 +338,16 @@ class Skeleton {
}
_setPose() {
if (this._clips[0]) {
const clip = this._clips[0].clip;
const maps = this._clips[0].maps;
if (this._animations[0]) {
const animator = this._animations[0].animator;
const maps = this._animations[0].maps;
for (let i = 0; i < this.joints.length; i++) {
const joint = this.joints[i];
if (maps[i] === -1) {
continue;
}
const pose = clip.tracks[maps[i]];
const pose = animator.tracks[maps[i]];
const node = joint.node;
if (node) {
// Not update if there is no data.

View File

@ -2,7 +2,6 @@ import Texture, { TextureImageSource, TextureOpts, TexturePixelSource } from './
import glenum from './core/glenum';
import vendor from './core/vendor';
import Renderer from './Renderer';
import * as mathUtil from './math/util';
import { GLEnum } from './core/type';
function nearestPowerOfTwo(val: number) {
@ -112,11 +111,6 @@ class Texture2D extends Texture {
}
}
constructor(opts?: Partial<Texture2DOpts>) {
opts = opts || {};
super(opts);
}
update(renderer: Renderer) {
const _gl = renderer.gl;
_gl.bindTexture(_gl.TEXTURE_2D, this._cache.get('webgl_texture'));

View File

@ -21,7 +21,7 @@ export interface TextureCubeOpts extends TextureOpts, TextureCubeData {
/**
* @type {Array.<Object>}
*/
mipmaps: TextureCubeData[];
mipmaps?: TextureCubeData[];
}
interface TextureCube extends TextureCubeOpts {}
@ -54,10 +54,6 @@ interface TextureCube extends TextureCubeOpts {}
*/
class TextureCube extends Texture {
readonly textureType = 'textureCube';
constructor(opts?: Partial<TextureCubeOpts>) {
opts = opts || {};
super(opts);
}
get width() {
const images = this.image;
@ -103,6 +99,7 @@ class TextureCube extends Texture {
this.updateCommon(renderer);
const glFormat = this.format;
const mipmaps = this.mipmaps;
let glType = this.type;
_gl.texParameteri(_gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_S, this.getAvailableWrapS());
@ -128,11 +125,11 @@ class TextureCube extends Texture {
}
}
if (this.mipmaps.length) {
if (mipmaps && mipmaps.length) {
let width = this.width;
let height = this.height;
for (let i = 0; i < this.mipmaps.length; i++) {
const mipmap = this.mipmaps[i];
for (let i = 0; i < mipmaps.length; i++) {
const mipmap = mipmaps[i];
this._updateTextureData(_gl, mipmap, i, width, height, glFormat, glType);
width /= 2;
height /= 2;

View File

@ -54,9 +54,7 @@ export default class Timeline extends Notifier {
constructor(opts?: TimelineOption) {
super();
opts = opts || {};
this.stage = opts.stage || {};
this.stage = (opts && opts.stage) || {};
}
/**

View File

@ -1,6 +1,11 @@
import Timeline from '../Timeline';
import Clip from './Clip';
/**
* Animator will control animation play.
*
* We don't name it Animation to avoid conflicts with DOM API.
*/
export interface Animator {
timeline?: Timeline;

View File

@ -29,16 +29,12 @@ class Blend1DAnimator extends BlendAnimator {
private _cacheKey: number = 0;
private _cachePosition: number = -Infinity;
private _loop?: boolean;
private _elpasedTime?: number;
protected _output?: BlendAnimatorTarget;
protected _inputs: Blend1DAnimatorInput[];
constructor(opts?: Partial<Blend1DAnimatorOpts>) {
opts = opts || {};
super(opts);
opts = opts || {};
this._inputs = (opts.inputs || []).sort(clipSortFunc);
this._output = opts.output;

View File

@ -3,11 +3,6 @@
import Vector2 from '../math/Vector2';
import delaunay from '../util/delaunay';
import { BlendAnimator, BlendAnimatorOpts, BlendAnimatorTarget } from './BlendAnimator';
import Clip from './Clip';
const clipSortFunc = function (a: { position: number }, b: { position: number }) {
return a.position - b.position;
};
interface Blend2DAnimatorInput {
position: Vector2;
@ -32,9 +27,6 @@ interface Triangle {
class Blend2DAnimator extends BlendAnimator {
position = new Vector2();
private _cacheKey: number = 0;
private _cachePosition: number = -Infinity;
protected _output?: BlendAnimatorTarget;
protected _inputs: Blend2DAnimatorInput[];
@ -42,9 +34,8 @@ class Blend2DAnimator extends BlendAnimator {
private _triangles?: Triangle[];
constructor(opts?: Partial<Blend2DAnimatorOpts>) {
opts = opts || {};
super();
opts = opts || {};
this._inputs = opts.inputs || [];
this._output = opts.output;

View File

@ -22,8 +22,9 @@ class OrthographicCamera extends Camera {
bottom = -1;
constructor(opts?: Partial<OrthographicCameraOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts || {});
this.update();
}
updateProjectionMatrix() {
@ -40,7 +41,7 @@ class OrthographicCamera extends Camera {
this.far = -(1 - m[14]) / m[10];
}
clone() {
const camera = super.call(this);
const camera = super.clone.call(this);
camera.left = this.left;
camera.right = this.right;
camera.near = this.near;

View File

@ -27,6 +27,12 @@ class PerspectiveCamera extends Camera {
near = 0.1;
far = 2000;
constructor(opts?: Partial<PerspectiveCameraOpts>) {
super(opts);
Object.assign(this, opts);
this.update();
}
updateProjectionMatrix() {
const rad = (this.fov / 180) * Math.PI;
this.projectionMatrix.perspective(rad, this.aspect, this.near, this.far);

4
src/camera/index.ts Normal file
View File

@ -0,0 +1,4 @@
import Orthographic from './Orthographic';
import Perspective from './Perspective';
export { Orthographic, Perspective };

47
src/claygl.ts Normal file
View File

@ -0,0 +1,47 @@
export { default as Renderer } from './Renderer';
export { default as Material } from './Material';
export { default as Shader } from './Shader';
export { default as Geometry } from './Geometry';
export { default as Node } from './Node';
export { default as Renderable } from './Renderable';
export { default as Mesh } from './Mesh';
export { default as InstancedMesh } from './InstancedMesh';
export { default as GeometryBase } from './GeometryBase';
export { default as Skeleton } from './Skeleton';
export { default as Joint } from './Joint';
export { default as FrameBuffer } from './FrameBuffer';
export { default as Scene } from './Scene';
export { default as Timeline } from './Timeline';
export { default as Texture2D } from './Texture2D';
export { default as TextureCube } from './TextureCube';
export {
Perspective as PerspectiveCamera,
Orthographic as OrthographicCamera
} from './camera/index';
export {
Ambient as AmbientLight,
AmbientCubemap as AmbientCubemapLight,
AmbientSH as AmbientSHLight,
Directional as DirectionalLight,
Point as PointLight,
Sphere as SphereLight,
Spot as SpotLight,
Tube as TubeLight
} from './light/index';
export {
Cone as ConeGeometry,
Cube as CubeGeometry,
Cylinder as CylinderGeometry,
ParametricSurface as ParametricSurfaceGeometry,
Plane as PlaneGeometry,
Sphere as SphereGeometry
} from './geometry/index';
export * from './math';
export { color } from './core';
export * as easing from './animation/easing';

View File

@ -1,5 +1,3 @@
// @ts-nocheck
import Base from '../core/Base';
import OrthoCamera from '../camera/Orthographic';
import Plane from '../geometry/Plane';
import Shader from '../Shader';
@ -7,6 +5,12 @@ import Material from '../Material';
import Mesh from '../Mesh';
import glenum from '../core/glenum';
import vertexGlsl from '../shader/source/compositor/vertex.glsl.js';
import { GLEnum } from '../core/type';
import { optional } from '../core/util';
import type Renderer from '../Renderer';
import type FrameBuffer from '../FrameBuffer';
import type Texture2D from '../Texture2D';
import Notifier from '../core/Notifier';
Shader.import(vertexGlsl);
@ -17,187 +21,148 @@ const mesh = new Mesh({
});
const camera = new OrthoCamera();
/**
* @constructor clay.compositor.Pass
* @extends clay.core.Base
*/
const Pass = Base.extend(
function () {
return /** @lends clay.compositor.Pass# */ {
/**
* Fragment shader string
* @type {string}
*/
// PENDING shader or fragment ?
fragment: '',
interface CompositorFullscreenQuadPassOpts {
clearColor?: boolean;
clearDepth?: boolean;
blendWithPrevious?: boolean;
}
/**
* @type {Object}
*/
outputs: null,
class CompositorFullscreenQuadPass extends Notifier {
material: Material;
/**
* @type {clay.Material}
*/
material: null,
clearColor?: boolean;
clearDepth?: boolean;
blendWithPrevious?: boolean;
/**
* @type {Boolean}
*/
blendWithPrevious: false,
outputs: Record<string, Texture2D | undefined> = {};
/**
* @type {Boolean}
*/
clearColor: false,
constructor(fragment: string, opts?: Partial<CompositorFullscreenQuadPassOpts>) {
super();
/**
* @type {Boolean}
*/
clearDepth: true
};
},
function () {
const shader = new Shader(Shader.source('clay.compositor.vertex'), this.fragment);
const shader = new Shader(Shader.source('clay.compositor.vertex'), fragment);
const material = new Material({
shader: shader
});
material.enableTexturesAll();
this.material = material;
},
/** @lends clay.compositor.Pass.prototype */
{
/**
* @param {string} name
* @param {} value
*/
setUniform: function (name, value) {
this.material.setUniform(name, value);
},
/**
* @param {string} name
* @return {}
*/
getUniform: function (name) {
const uniform = this.material.uniforms[name];
if (uniform) {
return uniform.value;
}
},
/**
* @param {clay.Texture} texture
* @param {number} attachment
*/
attachOutput: function (texture, attachment) {
if (!this.outputs) {
this.outputs = {};
}
attachment = attachment || glenum.COLOR_ATTACHMENT0;
this.outputs[attachment] = texture;
},
/**
* @param {clay.Texture} texture
*/
detachOutput: function (texture) {
for (const attachment in this.outputs) {
if (this.outputs[attachment] === texture) {
this.outputs[attachment] = null;
}
}
},
bind: function (renderer, frameBuffer) {
if (this.outputs) {
for (const attachment in this.outputs) {
const texture = this.outputs[attachment];
if (texture) {
frameBuffer.attach(texture, attachment);
}
}
}
if (frameBuffer) {
frameBuffer.bind(renderer);
}
},
unbind: function (renderer, frameBuffer) {
frameBuffer.unbind(renderer);
},
/**
* @param {clay.Renderer} renderer
* @param {clay.FrameBuffer} [frameBuffer]
*/
render: function (renderer, frameBuffer) {
const _gl = renderer.gl;
if (frameBuffer) {
this.bind(renderer, frameBuffer);
// MRT Support in chrome
// https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html
const ext = renderer.getGLExtension('EXT_draw_buffers');
if (ext && this.outputs) {
const bufs = [];
for (let attachment in this.outputs) {
attachment = +attachment;
if (attachment >= _gl.COLOR_ATTACHMENT0 && attachment <= _gl.COLOR_ATTACHMENT0 + 8) {
bufs.push(attachment);
}
}
ext.drawBuffersEXT(bufs);
}
}
this.trigger('beforerender', this, renderer);
// FIXME Don't clear in each pass in default, let the color overwrite the buffer
// FIXME pixels may be discard
let clearBit = this.clearDepth ? _gl.DEPTH_BUFFER_BIT : 0;
_gl.depthMask(true);
if (this.clearColor) {
clearBit = clearBit | _gl.COLOR_BUFFER_BIT;
_gl.colorMask(true, true, true, true);
const cc = this.clearColor;
if (Array.isArray(cc)) {
_gl.clearColor(cc[0], cc[1], cc[2], cc[3]);
}
}
_gl.clear(clearBit);
if (this.blendWithPrevious) {
// Blend with previous rendered scene in the final output
// FIXME Configure blend.
// FIXME It will cause screen blink
_gl.enable(_gl.BLEND);
this.material.transparent = true;
} else {
_gl.disable(_gl.BLEND);
this.material.transparent = false;
}
this.renderQuad(renderer);
this.trigger('afterrender', this, renderer);
if (frameBuffer) {
this.unbind(renderer, frameBuffer);
}
},
/**
* Simply do quad rendering
*/
renderQuad: function (renderer) {
mesh.material = this.material;
renderer.renderPass([mesh], camera);
},
/**
* @param {clay.Renderer} renderer
*/
dispose: function (renderer) {}
opts = opts || {};
this.clearColor = opts.clearColor || false;
this.blendWithPrevious = opts.blendWithPrevious || false;
this.clearDepth = optional(opts.clearColor, true);
}
);
export default Pass;
setUniform(name: string, value: any) {
this.material.setUniform(name, value);
}
getUniform(name: string) {
const uniform = this.material.uniforms[name];
if (uniform) {
return uniform.value;
}
}
attachOutput(texture: Texture2D, attachment?: GLEnum) {
if (!this.outputs) {
this.outputs = {};
}
attachment = attachment || glenum.COLOR_ATTACHMENT0;
this.outputs[attachment] = texture;
}
/**
* @param {clay.Texture} texture
*/
detachOutput(texture: Texture2D) {
for (const attachment in this.outputs) {
if (this.outputs[attachment] === texture) {
this.outputs[attachment] = undefined;
}
}
}
bind(renderer: Renderer, frameBuffer: FrameBuffer) {
for (const attachment in this.outputs) {
const texture = this.outputs[attachment];
if (texture) {
frameBuffer.attach(texture, +attachment);
}
}
if (frameBuffer) {
frameBuffer.bind(renderer);
}
}
unbind(renderer: Renderer, frameBuffer: FrameBuffer) {
frameBuffer.unbind(renderer);
}
render(renderer: Renderer, frameBuffer: FrameBuffer) {
const _gl = renderer.gl;
if (frameBuffer) {
this.bind(renderer, frameBuffer);
// MRT Support in chrome
// https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html
const ext = renderer.getGLExtension('EXT_draw_buffers');
if (ext && this.outputs) {
const bufs = [];
for (const attachment in this.outputs) {
if (+attachment >= _gl.COLOR_ATTACHMENT0 && +attachment <= _gl.COLOR_ATTACHMENT0 + 8) {
bufs.push(attachment);
}
}
ext.drawBuffersEXT(bufs);
}
}
this.trigger('beforerender', this, renderer);
// FIXME Don't clear in each pass in default, let the color overwrite the buffer
// FIXME pixels may be discard
let clearBit = this.clearDepth ? _gl.DEPTH_BUFFER_BIT : 0;
_gl.depthMask(true);
if (this.clearColor) {
clearBit = clearBit | _gl.COLOR_BUFFER_BIT;
_gl.colorMask(true, true, true, true);
const cc = this.clearColor;
if (Array.isArray(cc)) {
_gl.clearColor(cc[0], cc[1], cc[2], cc[3]);
}
}
_gl.clear(clearBit);
if (this.blendWithPrevious) {
// Blend with previous rendered scene in the final output
// FIXME Configure blend.
// FIXME It will cause screen blink
_gl.enable(_gl.BLEND);
this.material.transparent = true;
} else {
_gl.disable(_gl.BLEND);
this.material.transparent = false;
}
this.renderQuad(renderer);
this.trigger('afterrender', this, renderer);
if (frameBuffer) {
this.unbind(renderer, frameBuffer);
}
}
/**
* Simply do quad rendering
*/
renderQuad(renderer: Renderer) {
mesh.material = this.material;
renderer.renderPass([mesh], camera);
}
/**
* @param {clay.Renderer} renderer
*/
dispose(renderer: Renderer) {}
}
export default CompositorFullscreenQuadPass;

View File

@ -1,18 +1,14 @@
// @ts-nocheck
import Texture2D from '../Texture2D';
import glenum from '../core/glenum';
import * as util from '../core/util';
import Texture, { TextureOpts } from '../Texture';
import Renderer from '../Renderer';
const TexturePool = function () {
this._pool = {};
class TexturePool {
private _pool: Record<string, Texture[]> = {};
private _allocatedTextures: Texture[] = [];
this._allocatedTextures = [];
};
TexturePool.prototype = {
constructor: TexturePool,
get: function (parameters) {
get(parameters: Partial<TextureOpts>) {
const key = generateKey(parameters);
if (!util.hasOwn(this._pool, key)) {
this._pool[key] = [];
@ -24,27 +20,26 @@ TexturePool.prototype = {
return texture;
}
return list.pop();
},
}
put: function (texture) {
put(texture: Texture) {
const key = generateKey(texture);
if (!util.hasOwn(this._pool, key)) {
this._pool[key] = [];
}
const list = this._pool[key];
list.push(texture);
},
}
clear: function (renderer) {
clear(renderer: Renderer) {
for (let i = 0; i < this._allocatedTextures.length; i++) {
this._allocatedTextures[i].dispose(renderer);
}
this._pool = {};
this._allocatedTextures = [];
}
};
const defaultParams = {
}
const defaultParams: Partial<TextureOpts> = {
width: 512,
height: 512,
type: glenum.UNSIGNED_BYTE,
@ -58,24 +53,22 @@ const defaultParams = {
flipY: true,
unpackAlignment: 4,
premultiplyAlpha: false
};
} as const;
const defaultParamPropList = Object.keys(defaultParams);
function generateKey(parameters) {
util.defaultsWithPropList(parameters, defaultParams, defaultParamPropList);
function generateKey(parameters: Partial<TextureOpts>) {
util.defaults(parameters, defaultParams);
fallBack(parameters);
let key = '';
for (let i = 0; i < defaultParamPropList.length; i++) {
const name = defaultParamPropList[i];
const chunk = parameters[name].toString();
key += chunk;
key += (parameters as any)[defaultParamPropList[i]].toString();
}
return key;
}
function fallBack(target) {
function fallBack(target: any) {
const IPOT = isPowerOfTwo(target.width, target.height);
if (target.format === glenum.DEPTH_COMPONENT) {
@ -101,7 +94,7 @@ function fallBack(target) {
}
}
function isPowerOfTwo(width, height) {
function isPowerOfTwo(width: number, height: number) {
return (width & (width - 1)) === 0 && (height & (height - 1)) === 0;
}

8
src/core/index.ts Normal file
View File

@ -0,0 +1,8 @@
import * as color from './color';
import LinkedList from './LinkedList';
import LRU from './LRU';
import Notifier from './Notifier';
import * as request from './request';
import * as util from './util';
export { color, LinkedList, LRU, Notifier, request, util };

View File

@ -23,7 +23,6 @@ class ConeGeometry extends Geometry {
heightSegments = 1;
constructor(opts?: Partial<ConeGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

View File

@ -23,7 +23,6 @@ class CubeGeometry extends Geometry {
inside = false;
constructor(opts?: Partial<CubeGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

View File

@ -16,7 +16,6 @@ class CylinderGeometry extends Geometry {
heightSegments = 1;
constructor(opts?: Partial<CylinderGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

View File

@ -18,7 +18,6 @@ class ParametricSurfaceGeometry extends Geometry {
generator: SurfaceGenerator;
constructor(opts?: Partial<ParametricSurfaceGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

View File

@ -12,7 +12,6 @@ class PlaneGeometry extends Geometry {
heightSegments = 1;
constructor(opts?: Partial<PlaneGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

View File

@ -26,7 +26,6 @@ class SphereGeometry extends Geometry {
radius = 1;
constructor(opts?: Partial<SphereGeometryOpts>) {
opts = opts || {};
super(opts);
Object.assign(this, opts);
this.build();

8
src/geometry/index.ts Normal file
View File

@ -0,0 +1,8 @@
import Cone from './Cone';
import Cube from './Cube';
import Cylinder from './Cylinder';
import ParametricSurface from './ParametricSurface';
import Plane from './Plane';
import Sphere from './Sphere';
export { Cone, Cube, Cylinder, ParametricSurface, Plane, Sphere };

View File

@ -502,7 +502,7 @@ export const forEach = (function () {
for (i = offset; i < l; i += stride) {
vec[0] = a[i];
vec[1] = a[i + 1];
fn(vec, vec, arg);
fn(vec, vec, arg as T);
a[i] = vec[0];
a[i + 1] = vec[1];
}

View File

@ -627,7 +627,7 @@ export const forEach = (function () {
vec[0] = a[i];
vec[1] = a[i + 1];
vec[2] = a[i + 2];
fn(vec, vec, arg);
fn(vec, vec, arg as T);
a[i] = vec[0];
a[i + 1] = vec[1];
a[i + 2] = vec[2];

View File

@ -521,7 +521,7 @@ export const forEach = (function () {
vec[1] = a[i + 1];
vec[2] = a[i + 2];
vec[3] = a[i + 3];
fn(vec, vec, arg);
fn(vec, vec, arg as T);
a[i] = vec[0];
a[i + 1] = vec[1];
a[i + 2] = vec[2];

View File

@ -44,7 +44,9 @@ function unrollLoop(
// PENDING Add scope?
unroll +=
'{' +
snippet.replace(/float\s*\(\s*_idx_\s*\)/g, idx.toFixed(1)).replace(/_idx_/g, idx) +
snippet
.replace(/float\s*\(\s*_idx_\s*\)/g, idx.toFixed(1))
.replace(/_idx_/g, idx as any as string) +
'}';
}

View File

@ -27,10 +27,8 @@ class AmbientCubemapLight extends Light {
readonly type = 'AMBIENT_CUBEMAP_LIGHT';
constructor(opts?: Partial<AmbientCubemapLightOpts>) {
opts = opts || {};
super(opts);
this.cubemap = opts.cubemap;
this.cubemap = opts && opts.cubemap;
}
/**

View File

@ -10,9 +10,8 @@ class AmbientSHLight extends Light {
__coefficientsTmpArr = new Float32Array(9 * 3);
constructor(opts?: Partial<AmbientSHLightOpts>) {
opts = opts || {};
super(opts);
this.coefficients = opts.coefficients || [];
this.coefficients = (opts && opts.coefficients) || [];
}
clone() {

10
src/light/index.ts Normal file
View File

@ -0,0 +1,10 @@
import Ambient from './Ambient';
import AmbientCubemap from './AmbientCubemap';
import AmbientSH from './AmbientSH';
import Directional from './Directional';
import Point from './Point';
import Sphere from './Sphere';
import Spot from './Spot';
import Tube from './Tube';
export { Ambient, AmbientCubemap, AmbientSH, Directional, Point, Sphere, Spot, Tube };

View File

@ -25,7 +25,7 @@ import glenum from '../core/glenum';
import BoundingBox from '../math/BoundingBox';
import TrackAnimator from '../animation/TrackAnimator';
import TrackAnimation from '../animation/TrackAnimation';
import SamplerTrack from '../animation/SamplerTrack';
import Geometry from '../Geometry';
@ -1283,7 +1283,7 @@ const GLTFLoader = Base.extend(
for (const hash in tracks) {
tracksList.push(tracks[hash]);
}
const clip = new TrackAnimator({
const clip = new TrackAnimation({
name: animationInfo.name,
loop: true,
tracks: tracksList

27
src/math/index.ts Normal file
View File

@ -0,0 +1,27 @@
import Frustum from './Frustum';
import Matrix2 from './Matrix2';
import Matrix2d from './Matrix2d';
import Matrix3 from './Matrix3';
import Matrix4 from './Matrix4';
import Plane from './Plane';
import Quaternion from './Quaternion';
import Ray from './Ray';
import * as Value from './Value';
import Vector2 from './Vector2';
import Vector3 from './Vector3';
import Vector4 from './Vector4';
export {
Frustum,
Matrix2,
Matrix2d,
Matrix3,
Matrix4,
Plane,
Quaternion,
Ray,
Value,
Vector2,
Vector3,
Vector4
};

View File

@ -1,16 +1,42 @@
// @ts-nocheck
import Base from '../core/Base';
import Vector3 from '../math/Vector3';
import PerspectiveCamera from '../camera/Perspective';
import FrameBuffer from '../FrameBuffer';
import TextureCube from '../TextureCube';
const targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz'];
import type ShadowMapPass from './ShadowMap';
import type Renderer from '../Renderer';
import type Scene from '../Scene';
const targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz'] as const;
type CameraTarget = typeof targets[number];
interface EnvironmentMapPassOpts {
/**
* Camera position
*/
position: Vector3;
/**
* Camera far plane
*/
far: number;
/**
* Camera near plane
*/
near: number;
/**
* Environment cube map
*/
texture: TextureCube;
/**
* Used if you wan't have shadow in environment map
*/
shadowMapPass: ShadowMapPass;
}
/**
* Pass rendering scene to a environment cube map
*
* @constructor clay.prePass.EnvironmentMap
* @extends clay.core.Base
* @example
* // Example of car reflection
* const envMap = new clay.TextureCube({
@ -30,41 +56,36 @@ const targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz'];
* renderer.render(scene, camera);
* });
*/
const EnvironmentMapPass = Base.extend(
function () {
const ret = /** @lends clay.prePass.EnvironmentMap# */ {
/**
* Camera position
* @type {clay.Vector3}
* @memberOf clay.prePass.EnvironmentMap#
*/
position: new Vector3(),
/**
* Camera far plane
* @type {number}
* @memberOf clay.prePass.EnvironmentMap#
*/
far: 1000,
/**
* Camera near plane
* @type {number}
* @memberOf clay.prePass.EnvironmentMap#
*/
near: 0.1,
/**
* Environment cube map
* @type {clay.TextureCube}
* @memberOf clay.prePass.EnvironmentMap#
*/
texture: null,
class EnvironmentMapPass {
/**
* Camera position
*/
position = new Vector3();
/**
* Camera far plane
*/
far = 1000;
/**
* Camera near plane
*/
near = 0.1;
/**
* Environment cube map
*/
texture?: TextureCube;
/**
* Used if you wan't have shadow in environment map
* @type {clay.prePass.ShadowMap}
*/
shadowMapPass: null
};
const cameras = (ret._cameras = {
/**
* Used if you wan't have shadow in environment map
*/
shadowMapPass?: ShadowMapPass;
private _cameras: Record<CameraTarget, PerspectiveCamera>;
private _frameBuffer: FrameBuffer;
constructor(opts?: Partial<EnvironmentMapPassOpts>) {
Object.assign(this, opts);
const cameras = (this._cameras = {
px: new PerspectiveCamera({ fov: 90 }),
nx: new PerspectiveCamera({ fov: 90 }),
py: new PerspectiveCamera({ fov: 90 }),
@ -80,69 +101,53 @@ const EnvironmentMapPass = Base.extend(
cameras.nz.lookAt(Vector3.NEGATIVE_Z, Vector3.NEGATIVE_Y);
// FIXME In windows, use one framebuffer only renders one side of cubemap
ret._frameBuffer = new FrameBuffer();
this._frameBuffer = new FrameBuffer();
}
getCamera(target: CameraTarget) {
return this._cameras[target];
}
render(renderer: Renderer, scene: Scene, notUpdateScene?: boolean) {
const _gl = renderer.gl;
const texture = this.texture;
if (!notUpdateScene) {
scene.update();
}
if (!texture) {
console.error('texture not provided');
return;
}
// Tweak fov
// http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
const n = texture.width;
const fov = ((2 * Math.atan(n / (n - 0.5))) / Math.PI) * 180;
return ret;
},
/** @lends clay.prePass.EnvironmentMap# */ {
/**
* @param {string} target
* @return {clay.Camera}
*/
getCamera: function (target) {
return this._cameras[target];
},
/**
* @param {clay.Renderer} renderer
* @param {clay.Scene} scene
* @param {boolean} [notUpdateScene=false]
*/
render: function (renderer, scene, notUpdateScene) {
const _gl = renderer.gl;
if (!notUpdateScene) {
scene.update();
for (let i = 0; i < 6; i++) {
const target = targets[i];
const camera = this._cameras[target];
Vector3.copy(camera.position, this.position);
camera.far = this.far;
camera.near = this.near;
camera.fov = fov;
if (this.shadowMapPass) {
camera.update();
// update boundingBoxLastFrame
const bbox = scene.getBoundingBox();
bbox.applyTransform(camera.viewMatrix);
scene.viewBoundingBoxLastFrame.copy(bbox);
this.shadowMapPass.render(renderer, scene, camera, true);
}
// Tweak fov
// http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
const n = this.texture.width;
const fov = ((2 * Math.atan(n / (n - 0.5))) / Math.PI) * 180;
for (let i = 0; i < 6; i++) {
const target = targets[i];
const camera = this._cameras[target];
Vector3.copy(camera.position, this.position);
camera.far = this.far;
camera.near = this.near;
camera.fov = fov;
if (this.shadowMapPass) {
camera.update();
// update boundingBoxLastFrame
const bbox = scene.getBoundingBox();
bbox.applyTransform(camera.viewMatrix);
scene.viewBoundingBoxLastFrame.copy(bbox);
this.shadowMapPass.render(renderer, scene, camera, true);
}
this._frameBuffer.attach(
this.texture,
_gl.COLOR_ATTACHMENT0,
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i
);
this._frameBuffer.bind(renderer);
renderer.render(scene, camera, true);
this._frameBuffer.unbind(renderer);
}
},
/**
* @param {clay.Renderer} renderer
*/
dispose: function (renderer) {
this._frameBuffer.dispose(renderer);
this._frameBuffer.attach(texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
this._frameBuffer.bind(renderer);
renderer.render(scene, camera, true);
this._frameBuffer.unbind(renderer);
}
}
);
dispose(renderer: Renderer) {
this._frameBuffer.dispose(renderer);
}
}
export default EnvironmentMapPass;

View File

@ -5,13 +5,12 @@ import Texture2D from '../Texture2D';
import TextureCube, { TextureCubeOpts } from '../TextureCube';
import Texture from '../Texture';
import FrameBuffer from '../FrameBuffer';
import Pass from '../compositor/Pass';
import CompositorFullscreenQuadPass from '../compositor/Pass';
import Material from '../Material';
import Shader from '../Shader';
import Skybox from '../plugin/Skybox';
import Scene from '../Scene';
import EnvironmentMapPass from '../prePass/EnvironmentMap';
import vendor from '../core/vendor';
import textureUtil from './texture';
import integrateBRDFShaderCode from './shader/integrateBRDF.glsl.js';
@ -50,9 +49,9 @@ export function prefilterEnvironmentMap(
width: width,
height: height,
type: textureType,
flipY: false,
mipmaps: []
flipY: false
});
prefilteredCubeMap.mipmaps = [];
if (!prefilteredCubeMap.isPowerOfTwo()) {
console.warn('Width and height must be power of two to enable mipmap.');
@ -184,9 +183,7 @@ export function integrateBRDF(renderer: Renderer, normalDistribution: Texture2D)
const framebuffer = new FrameBuffer({
depthBuffer: false
});
const pass = new Pass({
fragment: integrateBRDFShaderCode
});
const quadPass = new CompositorFullscreenQuadPass(integrateBRDFShaderCode);
const texture = new Texture2D({
width: 512,
@ -198,10 +195,10 @@ export function integrateBRDF(renderer: Renderer, normalDistribution: Texture2D)
magFilter: Texture.NEAREST,
useMipmap: false
});
pass.setUniform('normalDistribution', normalDistribution);
pass.setUniform('viewportSize', [512, 256]);
pass.attachOutput(texture);
pass.render(renderer, framebuffer);
quadPass.setUniform('normalDistribution', normalDistribution);
quadPass.setUniform('viewportSize', [512, 256]);
quadPass.attachOutput(texture);
quadPass.render(renderer, framebuffer);
// FIXME Only chrome and firefox can readPixels with float type.
// framebuffer.bind(renderer);