(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); }(this, (function () { 'use strict'; var global = (0, eval)('this'); (function (global) { global.GLBoost = (typeof global.GLBoost !== 'undefined') ? global.GLBoost : {}; const GLBoost = global.GLBoost; if (typeof define === 'function' && define.amd) { define(function() { return GLBoost; }); } else if (typeof exports === 'object') { module.exports = GLBoost; global.GLBoost = GLBoost; } else { global.GLBoost = GLBoost; } (function(){ GLBoost.GLBOOST_CONSTANT_NAMES = []; GLBoost.GLBOOST_CONSTANT_VALUES = []; let c = { count: 0, __existedConstants: [], define: function (constantName, glConstantValue, aliasName) { let value = null; if (glConstantValue !== void 0 ) { value = glConstantValue; this.__existedConstants.push(glConstantValue); } else { const checkUnique = ()=> { let result = true; for (let existValue of this.__existedConstants) { if (this.count === existValue) { result = false; } } return result; }; for (; checkUnique() === false; this.count++) {} value = this.count; } GLBoost[constantName] = value; GLBoost.GLBOOST_CONSTANT_NAMES[value] = constantName; GLBoost.GLBOOST_CONSTANT_VALUES[value] = (typeof aliasName !== 'undefined') ? aliasName:constantName; this.count++; } }; // Define GLBoost Constants. /// copies of WebGL constants c.define('ACTIVE_ATTRIBUTES', 35721); c.define('ACTIVE_ATTRIBUTE_MAX_LENGTH', 35722); c.define('ACTIVE_TEXTURE', 34016); c.define('ACTIVE_UNIFORMS', 35718); c.define('ACTIVE_UNIFORM_MAX_LENGTH', 35719); c.define('ALIASED_LINE_WIDTH_RANGE', 33902); c.define('ALIASED_POINT_SIZE_RANGE', 33901); c.define('ALPHA', 6406); c.define('ALPHA_BITS', 3413); c.define('ALWAYS', 519); c.define('ARRAY_BUFFER', 34962); c.define('ARRAY_BUFFER_BINDING', 34964); c.define('ATTACHED_SHADERS', 35717); c.define('BACK', 1029); c.define('BLEND', 3042); c.define('BLEND_COLOR', 32773); c.define('BLEND_DST_ALPHA', 32970); c.define('BLEND_DST_RGB', 32968); c.define('BLEND_EQUATION', 32777); c.define('BLEND_EQUATION_ALPHA', 34877); c.define('BLEND_EQUATION_RGB', 32777); c.define('BLEND_SRC_ALPHA', 32971); c.define('BLEND_SRC_RGB', 32969); c.define('BLUE_BITS', 3412); c.define('BOOL', 35670); c.define('BOOL_VEC2', 35671); c.define('BOOL_VEC3', 35672); c.define('BOOL_VEC4', 35673); c.define('BROWSER_DEFAULT_WEBGL', 37444); c.define('BUFFER_SIZE', 34660); c.define('BUFFER_USAGE', 34661); c.define('BYTE', 5120); c.define('CCW', 2305); c.define('CLAMP_TO_EDGE', 33071); c.define('COLOR_ATTACHMENT0', 36064); c.define('COLOR_BUFFER_BIT', 16384); c.define('COLOR_CLEAR_VALUE', 3106); c.define('COLOR_WRITEMASK', 3107); c.define('COMPILE_STATUS', 35713); c.define('COMPRESSED_TEXTURE_FORMATS', 34467); c.define('CONSTANT_ALPHA', 32771); c.define('CONSTANT_COLOR', 32769); c.define('CONTEXT_LOST_WEBGL', 37442); c.define('CULL_FACE', 2884); c.define('CULL_FACE_MODE', 2885); c.define('CURRENT_PROGRAM', 35725); c.define('CURRENT_VERTEX_ATTRIB', 34342); c.define('CW', 2304); c.define('DECR', 7683); c.define('DECR_WRAP', 34056); c.define('DELETE_STATUS', 35712); c.define('DEPTH_ATTACHMENT', 36096); c.define('DEPTH_BITS', 3414); c.define('DEPTH_BUFFER_BIT', 256); c.define('DEPTH_CLEAR_VALUE', 2931); c.define('DEPTH_COMPONENT', 6402); c.define('DEPTH_COMPONENT16', 33189); c.define('DEPTH_FUNC', 2932); c.define('DEPTH_RANGE', 2928); c.define('DEPTH_STENCIL', 34041); c.define('DEPTH_STENCIL_ATTACHMENT', 33306); c.define('DEPTH_TEST', 2929); c.define('DEPTH_WRITEMASK', 2930); c.define('DITHER', 3024); c.define('DONT_CARE', 4352); c.define('DST_ALPHA', 772); c.define('DST_COLOR', 774); c.define('DYNAMIC_DRAW', 35048); c.define('ELEMENT_ARRAY_BUFFER', 34963); c.define('ELEMENT_ARRAY_BUFFER_BINDING', 34965); c.define('EQUAL', 514); c.define('FASTEST', 4353); c.define('FLOAT', 5126); c.define('FLOAT_MAT2', 35674); c.define('FLOAT_MAT3', 35675); c.define('FLOAT_MAT4', 35676); c.define('FLOAT_VEC2', 35664); c.define('FLOAT_VEC3', 35665); c.define('FLOAT_VEC4', 35666); c.define('FRAGMENT_SHADER', 35632); c.define('FRAMEBUFFER', 36160); c.define('FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', 36049); c.define('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', 36048); c.define('FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE', 36051); c.define('FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', 36050); c.define('FRAMEBUFFER_BINDING', 36006); c.define('FRAMEBUFFER_COMPLETE', 36053); c.define('FRAMEBUFFER_INCOMPLETE_ATTACHMENT', 36054); c.define('FRAMEBUFFER_INCOMPLETE_DIMENSIONS', 36057); c.define('FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT', 36055); c.define('FRAMEBUFFER_UNSUPPORTED', 36061); c.define('FRONT', 1028); c.define('FRONT_AND_BACK', 1032); c.define('FRONT_FACE', 2886); c.define('FUNC_ADD', 32774); c.define('FUNC_REVERSE_SUBTRACT', 32779); c.define('FUNC_SUBTRACT', 32778); c.define('GENERATE_MIPMAP_HINT', 33170); c.define('GEQUAL', 518); c.define('GREATER', 516); c.define('GREEN_BITS', 3411); c.define('HIGH_FLOAT', 36338); c.define('HIGH_INT', 36341); c.define('INCR', 7682); c.define('INCR_WRAP', 34055); c.define('INFO_LOG_LENGTH', 35716); c.define('INT', 5124); c.define('INT_VEC2', 35667); c.define('INT_VEC3', 35668); c.define('INT_VEC4', 35669); c.define('INVALID_ENUM', 1280); c.define('INVALID_FRAMEBUFFER_OPERATION', 1286); c.define('INVALID_OPERATION', 1282); c.define('INVALID_VALUE', 1281); c.define('INVERT', 5386); c.define('KEEP', 7680); c.define('LEQUAL', 515); c.define('LESS', 513); c.define('LINEAR', 9729); c.define('LINEAR_MIPMAP_LINEAR', 9987); c.define('LINEAR_MIPMAP_NEAREST', 9985); c.define('LINES', 1); c.define('LINE_LOOP', 2); c.define('LINE_STRIP', 3); c.define('LINE_WIDTH', 2849); c.define('LINK_STATUS', 35714); c.define('LOW_FLOAT', 36336); c.define('LOW_INT', 36339); c.define('LUMINANCE', 6409); c.define('LUMINANCE_ALPHA', 6410); c.define('MAX_COMBINED_TEXTURE_IMAGE_UNITS', 35661); c.define('MAX_CUBE_MAP_TEXTURE_SIZE', 34076); c.define('MAX_FRAGMENT_UNIFORM_VECTORS', 36349); c.define('MAX_RENDERBUFFER_SIZE', 34024); c.define('MAX_TEXTURE_IMAGE_UNITS', 34930); c.define('MAX_TEXTURE_SIZE', 3379); c.define('MAX_VARYING_VECTORS', 36348); c.define('MAX_VERTEX_ATTRIBS', 34921); c.define('MAX_VERTEX_TEXTURE_IMAGE_UNITS', 35660); c.define('MAX_VERTEX_UNIFORM_VECTORS', 36347); c.define('MAX_VIEWPORT_DIMS', 3386); c.define('MEDIUM_FLOAT', 36337); c.define('MEDIUM_INT', 36340); c.define('MIRRORED_REPEAT', 33648); c.define('NEAREST', 9728); c.define('NEAREST_MIPMAP_LINEAR', 9986); c.define('NEAREST_MIPMAP_NEAREST', 9984); c.define('NEVER', 512); c.define('NICEST', 4354); c.define('NONE', 0); c.define('NOTEQUAL', 517); c.define('NO_ERROR', 0); c.define('NUM_COMPRESSED_TEXTURE_FORMATS', 34466); c.define('ONE', 1); c.define('ONE_MINUS_CONSTANT_ALPHA', 32772); c.define('ONE_MINUS_CONSTANT_COLOR', 32770); c.define('ONE_MINUS_DST_ALPHA', 773); c.define('ONE_MINUS_DST_COLOR', 775); c.define('ONE_MINUS_SRC_ALPHA', 771); c.define('ONE_MINUS_SRC_COLOR', 769); c.define('OUT_OF_MEMORY', 1285); c.define('PACK_ALIGNMENT', 3333); c.define('POINTS', 0); c.define('POLYGON_OFFSET_FACTOR', 32824); c.define('POLYGON_OFFSET_FILL', 32823); c.define('POLYGON_OFFSET_UNITS', 10752); c.define('RED_BITS', 3410); c.define('RENDERBUFFER', 36161); c.define('RENDERBUFFER_ALPHA_SIZE', 36179); c.define('RENDERBUFFER_BINDING', 36007); c.define('RENDERBUFFER_BLUE_SIZE', 36178); c.define('RENDERBUFFER_DEPTH_SIZE', 36180); c.define('RENDERBUFFER_GREEN_SIZE', 36177); c.define('RENDERBUFFER_HEIGHT', 36163); c.define('RENDERBUFFER_INTERNAL_FORMAT', 36164); c.define('RENDERBUFFER_RED_SIZE', 36176); c.define('RENDERBUFFER_STENCIL_SIZE', 36181); c.define('RENDERBUFFER_WIDTH', 36162); c.define('RENDERER', 7937); c.define('REPEAT', 10497); c.define('REPLACE', 7681); c.define('RGB', 6407); c.define('RGB5_A1', 32855); c.define('RGB565', 36194); c.define('RGBA', 6408); c.define('RGBA4', 32854); c.define('SAMPLER_2D', 35678); c.define('SAMPLER_CUBE', 35680); c.define('SAMPLES', 32937); c.define('SAMPLE_ALPHA_TO_COVERAGE', 32926); c.define('SAMPLE_BUFFERS', 32936); c.define('SAMPLE_COVERAGE', 32928); c.define('SAMPLE_COVERAGE_INVERT', 32939); c.define('SAMPLE_COVERAGE_VALUE', 32938); c.define('SCISSOR_BOX', 3088); c.define('SCISSOR_TEST', 3089); c.define('SHADER_COMPILER', 36346); c.define('SHADER_SOURCE_LENGTH', 35720); c.define('SHADER_TYPE', 35663); c.define('SHADING_LANGUAGE_VERSION', 35724); c.define('SHORT', 5122); c.define('SRC_ALPHA', 770); c.define('SRC_ALPHA_SATURATE', 776); c.define('SRC_COLOR', 768); c.define('STATIC_DRAW', 35044); c.define('STENCIL_ATTACHMENT', 36128); c.define('STENCIL_BACK_FAIL', 34817); c.define('STENCIL_BACK_FUNC', 34816); c.define('STENCIL_BACK_PASS_DEPTH_FAIL', 34818); c.define('STENCIL_BACK_PASS_DEPTH_PASS', 34819); c.define('STENCIL_BACK_REF', 36003); c.define('STENCIL_BACK_VALUE_MASK', 36004); c.define('STENCIL_BACK_WRITEMASK', 36005); c.define('STENCIL_BITS', 3415); c.define('STENCIL_BUFFER_BIT', 1024); c.define('STENCIL_CLEAR_VALUE', 2961); c.define('STENCIL_FAIL', 2964); c.define('STENCIL_FUNC', 2962); c.define('STENCIL_INDEX', 6401); c.define('STENCIL_INDEX8', 36168); c.define('STENCIL_PASS_DEPTH_FAIL', 2965); c.define('STENCIL_PASS_DEPTH_PASS', 2966); c.define('STENCIL_REF', 2967); c.define('STENCIL_TEST', 2960); c.define('STENCIL_VALUE_MASK', 2963); c.define('STENCIL_WRITEMASK', 2968); c.define('STREAM_DRAW', 35040); c.define('SUBPIXEL_BITS', 3408); c.define('TEXTURE', 5890); c.define('TEXTURE0', 33984); c.define('TEXTURE1', 33985); c.define('TEXTURE2', 33986); c.define('TEXTURE3', 33987); c.define('TEXTURE4', 33988); c.define('TEXTURE5', 33989); c.define('TEXTURE6', 33990); c.define('TEXTURE7', 33991); c.define('TEXTURE8', 33992); c.define('TEXTURE9', 33993); c.define('TEXTURE10', 33994); c.define('TEXTURE11', 33995); c.define('TEXTURE12', 33996); c.define('TEXTURE13', 33997); c.define('TEXTURE14', 33998); c.define('TEXTURE15', 33999); c.define('TEXTURE16', 34000); c.define('TEXTURE17', 34001); c.define('TEXTURE18', 34002); c.define('TEXTURE19', 34003); c.define('TEXTURE20', 34004); c.define('TEXTURE21', 34005); c.define('TEXTURE22', 34006); c.define('TEXTURE23', 34007); c.define('TEXTURE24', 34008); c.define('TEXTURE25', 34009); c.define('TEXTURE26', 34010); c.define('TEXTURE27', 34011); c.define('TEXTURE28', 34012); c.define('TEXTURE29', 34013); c.define('TEXTURE30', 34014); c.define('TEXTURE31', 34015); c.define('TEXTURE_2D', 3553); c.define('TEXTURE_BINDING_2D', 32873); c.define('TEXTURE_BINDING_CUBE_MAP', 34068); c.define('TEXTURE_CUBE_MAP', 34067); c.define('TEXTURE_CUBE_MAP_NEGATIVE_X', 34070); c.define('TEXTURE_CUBE_MAP_NEGATIVE_Y', 34072); c.define('TEXTURE_CUBE_MAP_NEGATIVE_Z', 34074); c.define('TEXTURE_CUBE_MAP_POSITIVE_X', 34069); c.define('TEXTURE_CUBE_MAP_POSITIVE_Y', 34071); c.define('TEXTURE_CUBE_MAP_POSITIVE_Z', 34073); c.define('TEXTURE_MAG_FILTER', 10240); c.define('TEXTURE_MIN_FILTER', 10241); c.define('TEXTURE_WRAP_S', 10242); c.define('TEXTURE_WRAP_T', 10243); c.define('TRIANGLES', 4); c.define('TRIANGLE_FAN', 6); c.define('TRIANGLE_STRIP', 5); c.define('UNPACK_ALIGNMENT', 3317); c.define('UNPACK_COLORSPACE_CONVERSION_WEBGL', 37443); c.define('UNPACK_FLIP_Y_WEBGL', 37440); c.define('UNPACK_PREMULTIPLY_ALPHA_WEBGL', 37441); c.define('UNSIGNED_BYTE', 5121); c.define('UNSIGNED_INT', 5125); c.define('UNSIGNED_SHORT', 5123); c.define('UNSIGNED_SHORT_4_4_4_4', 32819); c.define('UNSIGNED_SHORT_5_5_5_1', 32820); c.define('UNSIGNED_SHORT_5_6_5', 33635); c.define('VALIDATE_STATUS', 35715); c.define('VENDOR', 7936); c.define('VERSION', 7938); c.define('VERTEX_ATTRIB_ARRAY_BUFFER_BINDING', 34975); c.define('VERTEX_ATTRIB_ARRAY_ENABLED', 34338); c.define('VERTEX_ATTRIB_ARRAY_NORMALIZED', 34922); c.define('VERTEX_ATTRIB_ARRAY_POINTER', 34373); c.define('VERTEX_ATTRIB_ARRAY_SIZE', 34339); c.define('VERTEX_ATTRIB_ARRAY_STRIDE', 34340); c.define('VERTEX_ATTRIB_ARRAY_TYPE', 34341); c.define('VERTEX_SHADER', 35633); c.define('VIEWPORT', 2978); c.define('ZERO', 0); /// GLBoost original constants c.define('POSITION', void 0, 'position'); c.define('COLOR', void 0, 'color'); c.define('NORMAL', void 0, 'normal'); c.define('TEXCOORD', void 0, 'texcoord'); c.define('TANGENT', void 0, 'tangent'); c.define('JOINT', void 0, 'joint'); c.define('WEIGHT', void 0, 'weight'); c.define('BLENDTARGET1', void 0, 'shapetarget_1'); c.define('BLENDTARGET2', void 0, 'shapetarget_2'); c.define('BLENDTARGET3', void 0, 'shapetarget_3'); c.define('BLENDTARGET4', void 0, 'shapetarget_4'); c.define('BLENDTARGET5', void 0, 'shapetarget_5'); c.define('BLENDTARGET6', void 0, 'shapetarget_6'); c.define('BLENDTARGET7', void 0, 'shapetarget_7'); c.define('BLENDTARGET8', void 0, 'shapetarget_8'); c.define('BLENDTARGET9', void 0, 'shapetarget_9'); c.define('BLENDTARGET10', void 0, 'shapetarget_10'); c.define('INTERPOLATION_LINEAR'); c.define('INTERPOLATION_STEP'); c.define('INTERPOLATION_CUBICSPLINE'); c.define('RADIAN', void 0, 'radian'); c.define('DEGREE', void 0, 'degree'); c.define('TEXTURE_PURPOSE_DIFFUSE', void 0, 'diffuse'); c.define('TEXTURE_PURPOSE_NORMAL', void 0, 'normal'); c.define('TEXTURE_PURPOSE_METALLIC_ROUGHNESS', void 0, 'metallic_roughness'); c.define('TEXTURE_PURPOSE_OCCLUSION', void 0, 'occlusion'); c.define('TEXTURE_PURPOSE_EMISSIVE', void 0, 'emissive'); c.define('TEXTURE_PURPOSE_BRDF_LUT', void 0, 'brdf_lut'); c.define('TEXTURE_PURPOSE_ENV_CUBE', void 0, 'env_cube'); c.define('TEXTURE_PURPOSE_IBL_DIFFUSE_ENV_CUBE', void 0, 'diffuse_ibl_env_cube'); c.define('TEXTURE_PURPOSE_IBL_SPECULAR_ENV_CUBE', void 0, 'specular_ibl_env_cube'); c.define('TEXTURE_PURPOSE_OTHERS', void 0, 'others'); c.define('QUERY_TYPE_INSTANCE_NAME'); c.define('QUERY_TYPE_USER_FLAVOR_NAME'); c.define('QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR'); c.define('QUERY_FORMAT_STRING_PARTIAL_MATCHING'); c.define('QUERY_FORMAT_STRING_PERFECT_MATCHING'); c.define('QUERY_FORMAT_REGEXP'); c.define('WORLD_MATRIX'); c.define('SHADER_PARAMETER_TYPE_OBJECT'); c.define('SHADER_PARAMETER_TYPE_MATERIAL'); c.define('SHADER_PARAMETER_TYPE_LIGHT'); c.define('SHADER_PARAMETER_TYPE_JOINTSET'); c.define('SHADER_PARAMETER_TYPE_MORPH'); c.define('GLOBAL_STATES_USAGE_DO_NOTHING'); c.define('GLOBAL_STATES_USAGE_IGNORE'); c.define('GLOBAL_STATES_USAGE_INCLUSIVE'); c.define('GLOBAL_STATES_USAGE_EXCLUSIVE'); c.define('LIFECYCLE_FHASE_CREATE'); c.define('LIFECYCLE_FHASE_LOAD'); c.define('LIFECYCLE_FHASE_MOUNT'); c.define('LIFECYCLE_FHASE_UPDATE_LOGIC'); c.define('LIFECYCLE_FHASE_UPDATE_FOR_RENDERING'); c.define('LIFECYCLE_FHASE_RENDER'); c.define('LIFECYCLE_FHASE_DISCARD'); c.define('LIFECYCLE_EVENT_CREATED'); c.define('LIFECYCLE_EVENT_LOADED'); c.define('LIFECYCLE_EVENT_MOUNTED'); c.define('LIFECYCLE_EVENT_UPDATED_LOGIC'); c.define('LIFECYCLE_EVENT_UPDATED_FOR_RENDERING'); c.define('LIFECYCLE_EVENT_RENDERED'); c.define('LIFECYCLE_EVENT_DISCARDED'); c.define('LOG_GENERAL'); c.define('LOG_SHADER_CODE'); c.define('LOG_GLBOOST_OBJECT_LIFECYCLE'); c.define('LOG_GL_RESOURCE_LIFECYCLE'); c.define('LOG_LEVEL_ERROR', void 0, 'error'); c.define('LOG_LEVEL_WARN', void 0, 'warn'); c.define('LOG_LEVEL_LOG', void 0, 'log'); c.define('LOG_LEVEL_INFO', void 0, 'info'); c.define('LOG_LEVEL_DEBUG', void 0, 'debug'); c.define('LOG_OMISSION_PROCESSING'); c.define('LOG_TYPE_NUMERICAL', void 0, 'numerical'); c.define('LOG_TYPE_AABB', void 0, 'AABB'); c.define('LOG_TYPE_GL', void 0, 'GL'); c.define('LOG_TYPE_PERFORMANCE', void 0, 'PERFORMANCE'); })(); GLBoost.isThisGLVersion_2 = function(gl) { if (typeof WebGL2RenderingContext === 'undefined') { return false; } return gl instanceof WebGL2RenderingContext; }; GLBoost.getNameOfGLBoostConstant = function(glboostConstant) { return GLBoost.GLBOOST_CONSTANT_NAMES[glboostConstant]; }; GLBoost.getValueOfGLBoostConstant = function(glboostConstant) { return GLBoost.GLBOOST_CONSTANT_VALUES[glboostConstant]; }; })(global); var GLBoost$1 = global.GLBoost; class GLExtensionsManager { constructor(glContext) { var gl = glContext.gl; if (GLBoost$1.VALUE_WEBGL_ONE_USE_EXTENSIONS) { this._extVAO = gl.getExtension('OES_vertex_array_object'); this._extDBs = gl.getExtension('WEBGL_draw_buffers'); this._extTFA = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic'); this._extEIUI = gl.getExtension('OES_element_index_uint'); this._extDepthTex = gl.getExtension('WEBGL_depth_texture'); this._extStdDerivatives = gl.getExtension("OES_standard_derivatives"); this._extTFL = gl.getExtension("OES_texture_float_linear"); this._extTexLod = gl.getExtension("EXT_shader_texture_lod"); } GLExtensionsManager._instances[glContext.belongingCanvasId] = this; this._glContext = glContext; } static getInstance(glContext) { if (GLExtensionsManager._instances[glContext.belongingCanvasId]) { return GLExtensionsManager._instances[glContext.belongingCanvasId]; } return new GLExtensionsManager(glContext); } get extVAO() { return this._extVAO; } get extDBs() { return this._extDBs; } get extTFA() { return this._extTFA; } get extDepthTex() { return this._extDepthTex; } createVertexArray(gl) { if (GLBoost$1.isThisGLVersion_2(gl)) { return gl.createVertexArray(); } else if (this._extVAO) { return this._extVAO.createVertexArrayOES(); } else { return null; } this._glContext.checkGLError(); } bindVertexArray(gl, vao) { if (GLBoost$1.isThisGLVersion_2(gl)) { gl.bindVertexArray(vao); return true; } else if (this._extVAO) { this._extVAO.bindVertexArrayOES(vao); return true; } else { return false; } this._glContext.checkGLError(); } drawBuffers(gl, buffers) { let buffer = buffers; if (GLBoost$1.isThisGLVersion_2(gl)) { gl.drawBuffers(buffers); buffer = buffer[0]; } else if (this._extDBs) { this.extDBs.drawBuffersWEBGL(buffers); buffer = buffer[0]; } if (buffer === gl.NONE) { gl.colorMask(false, false, false, false); } else { gl.colorMask(true, true, true, true); } this._glContext.checkGLError(); } readBuffer(gl, buffers) { let buffer = buffers; if (GLBoost$1.isThisGLVersion_2(gl)) { buffer = buffer[0]; } else if (this._extDBs) { buffer = buffer[0]; } gl.readBuffer(buffer); this._glContext.checkGLError(); } colorAttachiment(gl, index) { return this._extDBs ? this._extDBs[`COLOR_ATTACHMENT${index}_WEBGL`] : gl[`COLOR_ATTACHMENT${index}`]; } elementIndexBitSizeGLConstant(gl) { if (GLBoost$1.isThisGLVersion_2(gl) || this._extEIUI) { return gl.UNSIGNED_INT; } else { return gl.UNSIGNED_SHORT; } } elementIndexByteSizeNumber(gl) { if (GLBoost$1.isThisGLVersion_2(gl) || this._extEIUI) { return 4; } else { return 2; } } createUintArrayForElementIndex(gl, array) { if (GLBoost$1.isThisGLVersion_2(gl) || this._extEIUI) { return new Uint32Array(array); } else { return new Uint16Array(array); } } } GLExtensionsManager._instances = new Object(); GLBoost$1['GLExtensionsManager'] = GLExtensionsManager; class MiscUtil { constructor() { } static getTheValueOrAlternative(value, alternativeIfTheValueIsNullOrUndefined) { if (typeof value !== 'undefined' && value != null) { return value; } else { return alternativeIfTheValueIsNullOrUndefined; } } static isJavaScriptObjectType(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } static consoleLog(logType, text) { if (GLBoost$1.VALUE_CONSOLE_OUT_FOR_DEBUGGING && GLBoost$1.valueOfGLBoostConstants[logType]) { console.log(text); } } static isMobile() { var ua = [ "iPod", "iPad", "iPhone", "Android" ]; for (var i = 0; i < ua.length; i++) { if (navigator.userAgent.indexOf(ua[i]) > 0) { return true; } } return false; } static preventDefaultForDesktopOnly(e) { if(!MiscUtil.isMobile()) { e.preventDefault(); } } } GLBoost$1['MiscUtil'] = MiscUtil; class GLContextImpl { constructor(canvas, parent, initParameter) { // if (new.target === GLContextImpl) { if (this.constructor === GLContextImpl) { throw new TypeError("Cannot construct GLContextImpl instances directly"); } if (canvas === void 0) { throw new Error("Failed to create WebGL Context due to no canvas object."); } this._canvas = canvas; } init(glVersionString, ContextType, initParameter = { antialias: true, premultipliedAlpha: true }, gl) { if (gl) { this._gl = gl; } else { let gl = this._canvas.getContext(glVersionString, initParameter); if (!gl) { gl = this._canvas.getContext('experimental-' + glVersionString); if (!gl) { throw new Error("This platform doesn't support WebGL."); } } if (!gl instanceof ContextType) { throw new Error("Unexpected rendering context."); } this._gl = gl; } } get gl() { return this._gl; } set gl(gl) { this._gl = gl; } get canvas() { return this._canvas; } } class GLContextWebGL1Impl extends GLContextImpl { constructor(canvas, parent, initParameter, gl) { super(canvas, parent, initParameter); if (gl) { super.init('webgl', null, initParameter, gl); } else { super.init('webgl', WebGLRenderingContext, initParameter, gl); } } } class GLContextWebGL2Impl extends GLContextImpl { constructor(canvas, parent, initParameter, gl) { super(canvas, parent, initParameter); super.init('webgl2', WebGL2RenderingContext, initParameter, gl); } } /* */ let singleton = Symbol(); class L_GLBoostMonitor { constructor(enforcer ) { if (enforcer !== L_GLBoostMonitor._singletonEnforcer || !(this instanceof L_GLBoostMonitor)) { throw new Error('This is a Singleton class. get the instance using \'getInstance\' static method.'); } this._glBoostObjects = {}; this._glResources = []; L_GLBoostMonitor._singletonEnforcer = Symbol(); } static getInstance() { const that = this; if (!(that )[singleton]) { that[singleton] = new L_GLBoostMonitor(L_GLBoostMonitor._singletonEnforcer); } return that[singleton]; } registerGLBoostObject(glBoostObject ) { this._glBoostObjects[glBoostObject.instanceName] = glBoostObject; MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, 'GLBoost Resource: ' + glBoostObject.toString() + ' (' + glBoostObject.belongingCanvasId + ') was created.'); } deregisterGLBoostObject(glBoostObject ) { delete this._glBoostObjects[glBoostObject.instanceName]; MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, 'GLBoost Resource: ' + glBoostObject.toString() + ' (' + glBoostObject.belongingCanvasId + ') was ready for discard.'); } getGLBoostObjects(partOfGlBoostObjectInstanceName ) { let glBoostObjects = []; for (let instanceName in this._glBoostObjects) { if (instanceName.indexOf(partOfGlBoostObjectInstanceName)>0) { glBoostObjects.push(this._glBoostObjects[instanceName]); } } return glBoostObjects; } getGLBoostObject(glBoostObjectInstanceName ) { for (let instanceName in this._glBoostObjects) { if (instanceName === glBoostObjectInstanceName) { return this._glBoostObjects[instanceName]; } } return null; } getGLBoostObjectByUserFlavorName(glBoostObjectUserFlavorName ) { for (let instanceName in this._glBoostObjects) { if (this._glBoostObjects[instanceName].userFlavorName === glBoostObjectUserFlavorName) { return this._glBoostObjects[instanceName]; } } return null; } getGLBoostObjectsByUserFlavorName(partOfGlBoostObjectUserFlavorName ) { const results = []; for (let instanceName in this._glBoostObjects) { if (this._glBoostObjects[instanceName].userFlavorName.indexOf(partOfGlBoostObjectUserFlavorName) !== -1) { results.push(this._glBoostObjects[instanceName]); } } return results; } getGLBoostObjectWhichHasThisObjectId(objectId ) { for (let instanceName in this._glBoostObjects) { if (this._glBoostObjects[instanceName].objectIndex === objectId) { return this._glBoostObjects[instanceName]; } } return null; } printGLBoostObjects() { var objects = this._glBoostObjects; MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, '========== GLBoost Object Lists [begin] =========='); for (var key in objects) { if (objects.hasOwnProperty(key)) { MiscUtil.consoleLog(key + '(' + objects[key].belongingCanvasId + ')'); } } MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, '========== GLBoost Object Lists [end] =========='); } printGLBoostObjectsOrderByName() { var objects = this._glBoostObjects; var objectArray = []; for (var key in objects) { if (objects.hasOwnProperty(key)) { objectArray.push(objects[key]); } } objectArray.sort( function(a,b){ if( a < b ) return -1; if( a > b ) return 1; return 0; } ); MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, '========== GLBoost Object Lists [begin] =========='); objectArray.forEach((object)=>{ MiscUtil.consoleLog(object.toString() + ' (' + object.belongingCanvasId + ')'); }); MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, '========== GLBoost Object Lists [end] =========='); } registerWebGLResource(glBoostObject , glResource ) { var glResourceName = glResource.constructor.name; this._glResources.push([glBoostObject, glResource]); MiscUtil.consoleLog(GLBoost$1.LOG_GL_RESOURCE_LIFECYCLE, 'WebGL Resource: ' + glResourceName + ' was created by ' + glBoostObject.toString() + ' (' + glBoostObject.belongingCanvasId + ').'); } deregisterWebGLResource(glBoostObject , glResource ) { var glResourceName = glResource.constructor.name; this._glResources.forEach((glResource, i)=>{ if (glResource[0] === glBoostObject && glResource[1].constructor.name === glResourceName) { this._glResources.splice(i,1); } }); MiscUtil.consoleLog(GLBoost$1.LOG_GL_RESOURCE_LIFECYCLE, 'WebGL Resource: ' + glResourceName + ' was deleted by ' + glBoostObject.toString() + ' (' + glBoostObject.belongingCanvasId + ').'); } getWebGLResources(webglResourceName ) { let webglResources = this._glResources.filter((glResourceArray )=>{ if (glResourceArray[1].constructor.name === webglResourceName) { return true; } else { return false; } });//.map((glReourceArray)=>{return glReourceArray[1]}); return webglResources; } printWebGLResources() { var glResources = this._glResources; glResources.sort( function(a,b){ if( a[0] < b[0] ) return -1; if( a[0] > b[0] ) return 1; return 0; } ); MiscUtil.consoleLog(GLBoost$1.LOG_GL_RESOURCE_LIFECYCLE, '========== WebGL Resource Lists [begin] =========='); glResources.forEach((glResource, i)=>{ MiscUtil.consoleLog(i+1 +': ' + glResource[0].toString() + ' (' + glResource[0].belongingCanvasId + ') created ' + glResource[1]); }); MiscUtil.consoleLog(GLBoost$1.LOG_GL_RESOURCE_LIFECYCLE, '========== WebGL Resource Lists [end] =========='); } printHierarchy() { var glBoostObjects = this._glBoostObjects; var scenes = []; for (var key in glBoostObjects) { if (glBoostObjects.hasOwnProperty(key)) { if ( key.match(/Scene/)) { scenes.push(glBoostObjects[key]); } } } function putWhiteSpace(level) { var str = ''; for(var i=0; i { var outputText = (function searchRecursively(element, level) { var outputText = ''; outputText += putWhiteSpace(level) + element.toString() + ' (' + element.belongingCanvasId + ')\n'; if (typeof element.getChildren === 'undefined') { return outputText; } var children = element.getChildren(); children.forEach((child)=>{ outputText += searchRecursively(child, level+1); }); return outputText += '\n'; })(scene, 0); outputText = outputText.replace( /\n+/g , '\n'); MiscUtil.consoleLog(outputText); }); MiscUtil.consoleLog(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, '========== GLBoost Objects Hierarchy of Scenes [end] =========='); } } GLBoost$1['L_GLBoostMonitor'] = L_GLBoostMonitor; // let singleton$1 = Symbol(); let singletonEnforcer = Symbol(); class Logger { // Formatter // logFormatter:any; // Log Data Output Target /** * The constructor of Logger class. But you cannot use this constructor directly because of this class is a singleton class. Use getInstance() static method. * @param enforcer a Symbol to forbid calling this constructor directly */ constructor(enforcer ) { if (enforcer !== singletonEnforcer) { throw new Error("This is a Singleton class. get the instance using 'getInstance' static method."); } //this.logFormatter = null; this.realtimeTargets = new Map(); this.aggregateTargets = new Map(); this.logData = []; this.logCapacity = 5000; this.registerRealtimeOutputTarget('default', this.defaultConsoleFunction); this.registerAggregateOutputTarget('default', this.defaultConsoleFunction); } /** * The static method to get singleton instance of this class. * @return The singleton instance of GLTFLoader class */ static getInstance() { if (!this[singleton$1]) { this[singleton$1] = new Logger(singletonEnforcer); } return this[singleton$1]; } registerRealtimeOutputTarget(targetName, target) { this.realtimeTargets.set(targetName, target); } registerAggregateOutputTarget(targetName, target) { this.aggregateTargets.set(targetName, target); } unregisterRealtimeOutputTarget(targetName) { this.realtimeTargets.delete(targetName); } unregisterAggregateOutputTarget(targetName) { this.aggregateTargets.delete(targetName); } aggregate(targetName = null) { if (targetName != null) { const targetFunc = this.realtimeTargets[targetName]; for (const log of this.logData) { targetFunc(log.logLevelId, log.logTypeId, log.unixtime, ...log.args); } } else { for (var [targetName, targetFunc] of this.realtimeTargets) { for (const log of this.logData) { targetFunc(log.logLevelId, log.logTypeId, log.unixtime, ...log.args); } } } } out(logLevelId, logTypeId, isRealtimeOn, ...args) { if (GLBoost$1.VALUE_CONSOLE_OUT_FOR_DEBUGGING === false && (logLevelId === GLBoost$1.LOG_LEVEL_DEBUG || logLevelId === GLBoost$1.LOG_LEVEL_INFO || logLevelId === GLBoost$1.LOG_LEVEL_LOG)) { // output error log even when VALUE_CONSOLE_OUT_FOR_DEBUGGING is true. return; } if (GLBoost$1.valueOfGLBoostConstants[logTypeId] != null && GLBoost$1.valueOfGLBoostConstants[logTypeId] === false) { return; } const unixtime = Date.now(); this.logData.push({ unixtime: unixtime, logLevelId: logLevelId, logTypeId: logTypeId, args: args }); if (isRealtimeOn) { for (var [targetName, targetFunc] of this.realtimeTargets) { targetFunc(logLevelId, logTypeId, unixtime, ...args); } } if (this.logData.length > this.logCapacity + 1000) { this.logData.splice(0, this.logData.length - this.logCapacity); } } defaultConsoleFunction(logLevelId, logTypeId, unixtime, ...args) { //console[GLBoost.getValueOfGLBoostConstant(logLevelId)](`[${GLBoost.getValueOfGLBoostConstant(logTypeId)}] ${args}`); const d = new Date(unixtime); const year = d.getFullYear(); const month = d.getMonth() + 1; const day = d.getDate(); const hour = ( d.getHours() < 10 ) ? '0' + d.getHours() : d.getHours(); const min = ( d.getMinutes() < 10 ) ? '0' + d.getMinutes() : d.getMinutes(); const sec = ( d.getSeconds() < 10 ) ? '0' + d.getSeconds() : d.getSeconds(); const datestr = year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec; console[GLBoost$1.getValueOfGLBoostConstant(logLevelId)](`[${datestr}][${GLBoost$1.getValueOfGLBoostConstant(logTypeId)}] ${args}`); } } GLBoost$1['Logger'] = Logger; class GLContext { constructor(canvas, initParameter, gl, width, height) { if (typeof gl !== 'undefined' && gl !== null) { this.impl = new GLContextWebGL1Impl(canvas, initParameter, this, gl); this._canvasWidth = width; this._canvasHeight = height; GLContext._instances['nocanvas'] = this; } else { if (GLContext._instances[canvas.id] instanceof GLContext) { return GLContext._instances[canvas.id]; } if (GLBoost$1.VALUE_TARGET_WEBGL_VERSION === 1) { this.impl = new GLContextWebGL1Impl(canvas, this, initParameter); } else if (GLBoost$1.VALUE_TARGET_WEBGL_VERSION === 2) { this.impl = new GLContextWebGL2Impl(canvas, this, initParameter); } GLContext._instances[canvas.id] = this; this._canvasWidth = canvas.width; this._canvasHeight = canvas.height; } this._monitor = L_GLBoostMonitor.getInstance(); this._glslProgramsLatestUsageCount = 0; this._logger = Logger.getInstance(); this._glErrorTypes = ['INVALID_ENUM', 'INVALID_VALUE', 'INVALID_OPERATION', 'INVALID_FRAMEBUFFER_OPERATION', 'OUT_OF_MEMORY', 'CONTEXT_LOST_WEBGL']; this._glErrorMessages = [ 'An unacceptable value has been specified for an enumerated argument. The command is ignored and the error flag is set.', 'A numeric argument is out of range. The command is ignored and the error flag is set.', 'The specified command is not allowed for the current state. The command is ignored and the error flag is set.', 'The currently bound framebuffer is not framebuffer complete when trying to render to or to read from it.', 'Not enough memory is left to execute the command.', 'If the WebGL context is lost, this error is returned on the first call to getError. Afterwards and until the context has been restored, it returns gl.NO_ERROR.' ]; } static getInstance(canvas, initParameter, gl, width, height) { if (typeof canvas === 'string') { canvas = window.document.querySelector(canvas); } return new GLContext(canvas, initParameter, gl, width, height); } get gl() { return this.impl.gl; } set gl(gl) { this.impl.gl = gl; } get belongingCanvasId() { if (this.impl.canvas) { return this.impl.canvas.id; } else { return 'nocanvas'; } } get canvas() { return this.impl.canvas; } checkGLError() { if (GLBoost$1.valueOfGLBoostConstants[GLBoost$1.LOG_TYPE_GL] === false) { return; } let gl = this.impl.gl; let errorCode = gl.getError(); if (errorCode !== 0) { this.glErrorTypes.forEach((errorType, i)=>{ if (gl[errorType] === errorCode) { this._logger.out(GLBoost$1.LOG_LEVEL_ERROR, GLBoost$1.LOG_TYPE_GL, false, errorCode, this._glErrorMessages[i]); } }); } } createVertexArray(glBoostObject) { var gl = this.gl; var glem = GLExtensionsManager.getInstance(this); var glResource = glem.createVertexArray(gl); if (glResource) { this._monitor.registerWebGLResource(glBoostObject, glResource); } this.checkGLError(); return glResource; } createBuffer(glBoostObject) { var glResource = this.gl.createBuffer(); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } createFramebuffer(glBoostObject) { var glResource = this.gl.createFramebuffer(); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } deleteFramebuffer(glBoostObject, frameBuffer) { this._monitor.deregisterWebGLResource(glBoostObject, frameBuffer); this.gl.deleteFramebuffer(frameBuffer); this.checkGLError(); frameBuffer = null; } createRenderbuffer(glBoostObject) { var glResource = this.gl.createRenderbuffer(); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } deleteRenderbuffer(glBoostObject, renderBuffer) { this._monitor.deregisterWebGLResource(glBoostObject, renderBuffer); this.gl.deleteRenderbuffer(renderBuffer); this.checkGLError(); renderBuffer = null; } createShader(glBoostObject, shaderType) { var glResource = this.gl.createShader(shaderType); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } deleteShader(glBoostObject, shader) { this._monitor.deregisterWebGLResource(glBoostObject, shader); this.gl.deleteShader(shader); this.checkGLError(); shader = null; } createProgram(glBoostObject) { var glResource = this.gl.createProgram(); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } useProgram(program) { // if (!program) { this.gl.useProgram(program); this._currentProgramInuse = program; this.checkGLError(); this._glslProgramsLatestUsageCount++; /* return; } if (program.glslProgramsSelfUsageCount < this.glslProgramsLatestUsageCount) { this.gl.useProgram(program); this.checkGLError(); this._glslProgramsLatestUsageCount++; program.glslProgramsSelfUsageCount = this._glslProgramsLatestUsageCount; return; } MiscUtil.consoleLog(GLBoost.LOG_OMISSION_PROCESSING, 'LOG_OMISSION_PROCESSING: gl.useProgram call has been omitted since this glsl program is already in use.'); */ } deleteProgram(glBoostObject, program) { this._monitor.deregisterWebGLResource(glBoostObject, program); this.gl.deleteProgram(program); this.checkGLError(); } deleteAllPrograms() { let programObjs = this._monitor.getWebGLResources('WebGLProgram'); for (let programObj of programObjs) { this.deleteProgram(programObj[0], programObj[1]); } } getUniformLocation(glslProgram, uniformVariableName) { let uniformLocation = this.gl.getUniformLocation(glslProgram, uniformVariableName); this.checkGLError(); if (uniformLocation) { uniformLocation.glslProgram = glslProgram; uniformLocation.glslProgramUsageCountWhenLastSet = -1; } return uniformLocation; } _setUniformValues(uniformFuncStr, args, forceUpdate) { let uniformLocation = args[0]; if (!uniformLocation) { MiscUtil.consoleLog(GLBoost$1.LOG_OMISSION_PROCESSING, 'LOG_OMISSION_PROCESSING: gl.uniformXXX call has been omitted since the uniformLocation is falsy (undefined or something)'); return; } if (forceUpdate) { this.gl[uniformFuncStr].apply(this.gl, args); this.checkGLError(); return; } // this.gl[uniformFuncStr].apply(this.gl, args); /* if (uniformLocation.glslProgram.glslProgramsSelfUsageCount < this._glslProgramsLatestUsageCount) { MiscUtil.consoleLog(GLBoost.LOG_OMISSION_PROCESSING, 'LOG_OMISSION_PROCESSING: gl.uniformXXX call has been omitted since the uniformLocation.glslProgram is not in use.'); return; } */ if (this._currentProgramInuse.createdAt !== uniformLocation.glslProgram.createdAt) { console.error('missmatch!'); return; } if (uniformLocation.glslProgramUsageCountWhenLastSet < this._glslProgramsLatestUsageCount) { // Since I have never sent a uniform value to glslProgram which is currently in use, update it. this.gl[uniformFuncStr].apply(this.gl, args); args[0].setValue = args; this.checkGLError(); return; } MiscUtil.consoleLog(GLBoost$1.LOG_OMISSION_PROCESSING, 'LOG_OMISSION_PROCESSING: gl.uniformXXX call has been omitted since the uniformLocation.glslProgram is not in use.'); } // Set forceUpdate to true if there is no way to check whether the values (x, y, z, w) change from the previous states or not. uniformMatrix4fv(uniformLocation, toTranspose, matrix44, forceUpdate) { this._setUniformValues('uniformMatrix4fv', [uniformLocation, toTranspose, matrix44], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y, z, w) change from the previous states or not. uniform4f(uniformLocation, x, y, z, w, forceUpdate) { this._setUniformValues('uniform4f', [uniformLocation, x, y, z, w], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y, z) change from the previous states or not. uniform3f(uniformLocation, x, y, z, forceUpdate) { this._setUniformValues('uniform3f', [uniformLocation, x, y, z], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y) change from the previous states or not. uniform2f(uniformLocation, x, y, forceUpdate) { this._setUniformValues('uniform2f', [uniformLocation, x, y], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the value x changes from the previous state or not. uniform1f(uniformLocation, x, forceUpdate) { this._setUniformValues('uniform1f', [uniformLocation, x], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y, z, w) change from the previous states or not. uniform4i(uniformLocation, x, y, z, w, forceUpdate) { this._setUniformValues('uniform4i', [uniformLocation, x, y, z, w], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y, z) change from the previous states or not. uniform3i(uniformLocation, x, y, z, forceUpdate) { this._setUniformValues('uniform3i', [uniformLocation, x, y, z], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the values (x, y) change from the previous states or not. uniform2i(uniformLocation, x, y, forceUpdate) { this._setUniformValues('uniform2i', [uniformLocation, x, y], forceUpdate); } // Set forceUpdate to true if there is no way to check whether the value x changes from the previous state or not. uniform1i(uniformLocation, x, forceUpdate) { this._setUniformValues('uniform1i', [uniformLocation, x], forceUpdate); } createTexture(glBoostObject) { var glResource = this.gl.createTexture(); this._monitor.registerWebGLResource(glBoostObject, glResource); this.checkGLError(); return glResource; } deleteTexture(glBoostObject, texture) { this._monitor.deregisterWebGLResource(glBoostObject, texture); this.gl.deleteTexture(texture); this.checkGLError(); texture = null; } get canvasWidth() { return this._canvasWidth; } set canvasWidth(width) { if (this.impl.canvas) { this.impl.canvas.width = width; } this._canvasWidth = width; } get canvasHeight() { return this._canvasHeight; } set canvasHeight(height) { if (this.impl.canvas) { this.impl.canvas.height = height; } this._canvasHeight = height; } get glslProgramsLatestUsageCount() { return this._glslProgramsLatestUsageCount; } } GLContext._instances = new Object(); /* */ class GLBoostSystem { constructor(canvas , initParameter , gl , width , height , glBoostContext ) { if (gl) { this._glContext = GLContext.getInstance(null, initParameter, gl, width, height); } else { this._glContext = GLContext.getInstance(canvas, initParameter); } this._glBoostContext = glBoostContext; this._globalStatesUsage = GLBoost$1.GLOBAL_STATES_USAGE_INCLUSIVE; this._defaultGlobalStates = [ 3042, // gl.BLEND 2929 // gl.DEPTH_TEST ]; this._currentGlobalStates = null; this._glBoostMonitor = L_GLBoostMonitor.getInstance(); // effekseer if (typeof effekseer !== "undefined") { effekseer.init(this._glContext.gl); } } } // class Entity { constructor(entityUID , isAlive ) { this.__entity_uid = entityUID; this.__isAlive = isAlive; } } // let singleton$2 = Symbol(); class EntityRepository { //__entities: Array; constructor(enforcer ) { if (enforcer !== EntityRepository.__singletonEnforcer || !(this instanceof EntityRepository)) { throw new Error('This is a Singleton class. get the instance using \'getInstance\' static method.'); } EntityRepository.__singletonEnforcer = Symbol(); this.__entity_uid_count = 0; this.__entities = new Map(); this.__lifeStatusOfEntities = new Map(); } static getInstance() { if (!this[singleton$2]) { this[singleton$2] = new EntityRepository(EntityRepository.__singletonEnforcer); } return this[singleton$2]; } // assignEntityId(glBoostObject: GLBoostObject) { // if (glBoostObject.entityUID !== 0) { // console.warn('This GLBoostObject has been assigned entityUID already!'); // return false; // } // glBoostObject._entity_uid = ++this.__entity_uid_count; // this.__entities.push(glBoostObject); // return true; // } createEntity() { this.__entity_uid_count++; const alive = new Boolean(true); const entity = new Entity(this.__entity_uid_count, alive); this.__entities.set(this.__entity_uid_count, entity); this.__lifeStatusOfEntities.set(this.__entity_uid_count, alive); return entity; } } /* */ class GLBoostObject { constructor(glBoostSystem , toRegister = true) { if (this.constructor === GLBoostObject) { throw new TypeError('Cannot construct GLBoostObject instances directly.'); } this._entity_uid = 0; this._setName(); const entityRepository = EntityRepository.getInstance(); //entityRepository.assignEntityId(this); this._glBoostSystem = glBoostSystem; this._glContext = glBoostSystem._glContext; this._glBoostMonitor = glBoostSystem._glBoostMonitor; this._toRegister = toRegister; if (this._toRegister) { this._glBoostMonitor.registerGLBoostObject(this); } this._userFlavorName = ''; this._readyForDiscard = false; // generate the simple class-specific number. this._classUniqueNumber = 0; for(let i=0; i{ const that = this; let array = GLBoostObject['_' + typeName + 'ExistArray']; for (let i=0; i{ let array = GLBoostObject['_' + typeName + 'ExistArray']; const that = this; delete array[that['_' + typeName + 'Index']]; that['_' + typeName + 'Index'] = -1; }; if (this.className.indexOf('Mesh') !== -1) { deleteIndex('object'); if (this.className.indexOf('SkeltalMesh') !== -1) { deleteIndex('jointSet'); } } else if (this.className.indexOf('Light') !== -1) { deleteIndex('light'); } else if (this.className.indexOf('Material') !== -1) { deleteIndex('material'); } } _setName() { if (typeof GLBoostObject.classInfoDic[this.constructor.name] === 'undefined') { GLBoostObject.classInfoDic[this.constructor.name] = {}; } GLBoostObject.classInfoDic[this.constructor.name]._instanceCount = (typeof GLBoostObject.classInfoDic[this.constructor.name]._instanceCount === 'undefined') ? 0 : (GLBoostObject.classInfoDic[this.constructor.name]._instanceCount + 1); this._instanceName = this.constructor.name + '_' + GLBoostObject.classInfoDic[this.constructor.name]._instanceCount; } /** * Return instance name. * @returns the instance name. */ toString() { return this._instanceName; } /** * Return the simple class-specific number. */ get classUniqueNumber() { return this._classUniqueNumber; } get className() { return this.constructor.name; } get instanceName() { return this._instanceName; } get belongingCanvasId() { return this._glContext.belongingCanvasId; } set userFlavorName(name ) { this._userFlavorName = name; } tryToSetUserFlavorNameUniquely(name ) { if (this._glBoostMonitor.getGLBoostObjectByUserFlavorName(name) != null) { return false; } else { this._userFlavorName = name; return true; } } get userFlavorName() { return this._userFlavorName; } get instanceNameWithUserFlavor() { return this._instanceName + '__' + this._userFlavorName; } readyForDiscard() { if (this._toRegister) { this._glBoostMonitor.deregisterGLBoostObject(this); } this.tearDownExistIndexAndArray(); this._readyForDiscard = true; } get isReadyForDiscard() { return this._readyForDiscard; } _copy(instance) { instance._userFlavorName = this._userFlavorName; } get objectIndex() { return this._objectIndex; } get entityUID() { return this._entity_uid; } } GLBoostObject.classInfoDic = {}; GLBoostObject._objectExistArray = []; GLBoostObject.__entities = []; GLBoost$1['GLBoostObject'] = GLBoostObject; /* */ class Vector2 { constructor(x , y ) { if (ArrayBuffer.isView(x)) { this.v = ((x ) ); return; } else { this.v = new Float32Array(2); } this.x = ((x ) ); this.y = ((y ) ); } get className() { return this.constructor.name; } clone() { return new Vector2(this.x, this.y); } multiply(val ) { this.x *= val; this.y *= val; return this; } static multiply(vec2 , val ) { return new Vector2(vec2.x * val, vec2.y * val); } get x() { return this.v[0]; } set x(x ) { this.v[0] = x; } get y() { return this.v[1]; } set y(y ) { this.v[1] = y; } get raw() { return this.v; } } GLBoost$1["Vector2"] = Vector2; class MathUtil { constructor() { } static radianToDegree(rad) { return rad * 180 / Math.PI; } static degreeToRadian(deg) { return deg * Math.PI / 180; } } GLBoost$1["MathUtil"] = MathUtil; const IsUtil = { not: {}, all: {}, any: {}, _not(fn) { return function() { return !fn.apply(null, [...arguments]); }; }, _all(fn) { return function() { if (Array.isArray(arguments[0])) { return arguments[0].every(fn); } return [...arguments].every(fn); }; }, _any(fn) { return function() { if (Array.isArray(arguments[0])) { return arguments[0].some(fn); } return [...arguments].some(fn); }; }, defined(val) { return val !== void 0; }, undefined(val) { return val === void 0; }, null(val) { return val === null; }, // is NOT null or undefined exist(val) { return val != null; }, function(val) { return typeof val === "function"; } }; for (let fn in IsUtil) { if (IsUtil.hasOwnProperty(fn)) { const interfaces = ["not", "all", "any"]; if (fn.indexOf("_") === -1 && !interfaces.includes(fn)) { interfaces.forEach(itf => { const op = "_" + itf; IsUtil[itf][fn] = IsUtil[op](IsUtil[fn]); }); } } } GLBoost$1["IsUtil"] = IsUtil; // class Vector3 { constructor(x , y , z ) { if (ArrayBuffer.isView(x)) { this.v = ((x ) ); return; } else { this.v = new Float32Array(3); } if (IsUtil.not.exist(x)) { this.x = 0; this.y = 0; this.z = 0; } else if (Array.isArray(x)) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } else if (typeof (x ).w !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = (x ).z; } else if (typeof (x ).z !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = (x ).z; } else if (typeof (x ).y !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = 0; } else { this.x = ((x ) ); this.y = ((y ) ); this.z = ((z ) ); } } get className() { return this.constructor.name; } isEqual(vec ) { if (this.x === vec.x && this.y === vec.y && this.z === vec.z) { return true; } else { return false; } } /** * Zero Vector */ static zero() { return new Vector3(0, 0, 0); } clone() { return new Vector3(this.x, this.y, this.z); } length() { return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); } /* * disabled for now because Safari's Function.prototype.length is not configurable yet. */ /* static length(vec3) { return Math.sqrt(vec3.x*vec3.x + vec3.y*vec3.y + vec3.z*vec3.z); } */ /** * to square length */ lengthSquared() { return this.x*this.x + this.y*this.y + this.z*this.z; } /** * to square length(static verison) */ static lengthSquared(vec3 ) { return vec3.x*vec3.x + vec3.y*vec3.y + vec3.z*vec3.z; } lengthTo(vec3 ) { var deltaX = vec3.x - this.x; var deltaY = vec3.y - this.y; var deltaZ = vec3.z - this.z; return Math.sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ); } static lengthBtw(lhv , rhv ) { var deltaX = rhv.x - lhv.x; var deltaY = rhv.y - lhv.y; var deltaZ = rhv.z - lhv.z; return Math.sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ); } /** * dot product */ dotProduct(vec3 ) { return this.x * vec3.x + this.y * vec3.y + this.z * vec3.z; } /** * dot product(static version) */ static dotProduct(lv , rv ) { return lv.x * rv.x + lv.y * rv.y + lv.z * rv.z; } /** * cross product */ cross(v ) { var x = this.y*v.z - this.z*v.y; var y = this.z*v.x - this.x*v.z; var z = this.x*v.y - this.y*v.x; this.x = x; this.y = y; this.z = z; return this; } /** * cross product(static version) */ static cross(lv , rv ) { var x = lv.y*rv.z - lv.z*rv.y; var y = lv.z*rv.x - lv.x*rv.z; var z = lv.x*rv.y - lv.y*rv.x; return new Vector3(x, y, z); } /** * normalize */ normalize() { var length = this.length(); this.divide(length); return this; } /** * normalize(static version) */ static normalize(vec3 ) { var length = vec3.length(); var newVec = new Vector3(vec3.x, vec3.y, vec3.z); newVec.divide(length); return newVec; } /** * add value */ add(v ) { this.x += v.x; this.y += v.y; this.z += v.z; return this; } /** * add value(static version) */ static add(lv , rv ) { return new Vector3(lv.x + rv.x, lv.y + rv.y, lv.z + rv.z); } /** * subtract */ subtract(v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; } /** * subtract(subtract) */ static subtract(lv , rv ) { return new Vector3(lv.x - rv.x, lv.y - rv.y, lv.z - rv.z); } /** * divide */ divide(val ) { if (val !== 0) { this.x /= val; this.y /= val; this.z /= val; } else { console.warn("0 division occured!"); this.x = Infinity; this.y = Infinity; this.z = Infinity; } return this; } /** * divide(static version) */ static divide(vec3 , val ) { if (val !== 0) { return new Vector3(vec3.x / val, vec3.y / val, vec3.z / val); } else { console.warn("0 division occured!"); return new Vector3(Infinity, Infinity, Infinity); } } /** * multiply */ multiply(val ) { this.x *= val; this.y *= val; this.z *= val; return this; } /** * multiply vector */ multiplyVector(vec ) { this.x *= vec.x; this.y *= vec.y; this.z *= vec.z; return this; } /** * multiply(static version) */ static multiply(vec3 , val ) { return new Vector3(vec3.x * val, vec3.y * val, vec3.z * val); } /** * multiply vector(static version) */ static multiplyVector(vec3 , vec ) { return new Vector3(vec3.x * vec.x, vec3.y * vec.y, vec3.z * vec.z); } static angleOfVectors(lhv , rhv ) { let cos_sita = Vector3.dotProduct(lhv, rhv) / ( lhv.length() * rhv.length() ); let sita = Math.acos(cos_sita); if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { sita = MathUtil.radianToDegree(sita); } return sita; } /** * divide vector */ divideVector(vec3 ) { this.x /= vec3.x; this.y /= vec3.y; this.z /= vec3.z; return this; } /** * divide vector(static version) */ static divideVector(lvec3 , rvec3 ) { return new Vector3(lvec3.x / rvec3.x, lvec3.y / rvec3.y, lvec3.z / rvec3.z); } /** * change to string */ toString() { return '(' + this.x + ', ' + this.y + ', ' + this.z +')'; } get x() { return this.v[0]; } set x(x ) { this.v[0] = x; } get y() { return this.v[1]; } set y(y ) { this.v[1] = y; } get z() { return this.v[2]; } set z(z ) { this.v[2] = z; } get raw() { return this.v; } } GLBoost$1['Vector3'] = Vector3; // class Vector4$1 { constructor(x , y , z , w ) { if (ArrayBuffer.isView(x)) { this.v = ((x ) ); return; } else { this.v = new Float32Array(4); } if (IsUtil.not.exist(x)) { this.x = 0; this.y = 0; this.z = 0; this.w = 1; } else if (Array.isArray(x)) { this.x = x[0]; this.y = x[1]; this.z = x[2]; this.w = x[3]; } else if (typeof (x ).w !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = (x ).z; this.w = (x ).w; } else if (typeof (x ).z !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = (x ).z; this.w = 1; } else if (typeof (x ).y !== 'undefined') { this.x = (x ).x; this.y = (x ).y; this.z = 0; this.w = 1; } else { this.x = ((x ) ); this.y = ((y ) ); this.z = ((z ) ); this.w = ((w ) ); } } get className() { return this.constructor.name; } isEqual(vec ) { if (this.x === vec.x && this.y === vec.y && this.z === vec.z && this.w === vec.w) { return true; } else { return false; } } clone() { return new Vector4$1(this.x, this.y, this.z, this.w); } /** * Zero Vector */ static zero() { return new Vector4$1(0, 0, 0, 1); } length() { return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w); } normalize() { var length = this.length(); this.divide(length); return this; } static normalize(vec4 ) { var length = vec4.length(); var newVec = new Vector4$1(vec4.x, vec4.y, vec4.z, vec4.w); newVec.divide(length); return newVec; } /** * add value */ add(v ) { this.x += v.x; this.y += v.y; this.z += v.z; this.w += v.w; return this; } /** * add value(static version) */ static add(lv , rv ) { return new Vector4$1(lv.x + rv.x, lv.y + rv.y, lv.z + rv.z, lv.z + rv.z); } /** * add value except w component */ addWithOutW(v ) { this.x += v.x; this.y += v.y; this.z += v.z; return this; } subtract(v ) { this.x -= v.x; this.y -= v.y; this.z -= v.z; this.w -= v.w; return this; } static subtract(lv , rv ) { return new Vector4$1(lv.x - rv.x, lv.y - rv.y, lv.z - rv.z, lv.w - rv.w); } /** * add value except w component(static version) */ static addWithOutW(lv , rv ) { return new Vector4$1(lv.x + rv.x, lv.y + rv.y, lv.z + rv.z, lv.z); } multiply(val ) { this.x *= val; this.y *= val; this.z *= val; this.w *= val; return this; } multiplyVector(vec ) { this.x *= vec.x; this.y *= vec.y; this.z *= vec.z; this.w *= vec.w; return this; } static multiply(vec4 , val ) { return new Vector4$1(vec4.x * val, vec4.y * val, vec4.z * val, vec4.w * val); } static multiplyVector(vec4 , vec ) { return new Vector4$1(vec4.x * vec.x, vec4.y * vec.y, vec4.z * vec.z, vec4.w * vec.w); } divide(val ) { if (val !== 0) { this.x /= val; this.y /= val; this.z /= val; this.w /= val; } else { console.warn("0 division occured!"); this.x = Infinity; this.y = Infinity; this.z = Infinity; this.w = Infinity; } return this; } static divide(vec4 , val ) { if (val !== 0) { return new Vector4$1(vec4.x / val, vec4.y / val, vec4.z / val, vec4.w / val); } else { console.warn("0 division occured!"); return new Vector4$1(Infinity, Infinity, Infinity, Infinity); } } divideVector(vec4 ) { this.x /= vec4.x; this.y /= vec4.y; this.z /= vec4.z; this.w /= vec4.w; return this; } static divideVector(lvec4 , rvec4 ) { return new Vector4$1(lvec4.x / rvec4.x, lvec4.y / rvec4.y, lvec4.z / rvec4.z, lvec4.w / rvec4.w); } toString() { return '(' + this.x + ', ' + this.y + ', ' + this.z + ', ' + this.w + ')'; } get x() { return this.v[0]; } set x(x ) { this.v[0] = x; } get y() { return this.v[1]; } set y(y ) { this.v[1] = y; } get z() { return this.v[2]; } set z(z ) { this.v[2] = z; } get w() { return this.v[3]; } set w(w ) { this.v[3] = w; } get raw() { return this.v; } } GLBoost$1["Vector4"] = Vector4$1; class Quaternion { constructor(x, y, z, w) { this.x = x; this.y = y; this.z = z; this.w = w; } isEqual(vec) { if (this.x === vec.x && this.y === vec.y && this.z === vec.z && this.w === vec.w) { return true; } else { return false; } } get className() { return this.constructor.name; } clone() { return new Quaternion(this.x, this.y, this.z, this.w); } static invert(quat) { quat = new Quaternion(-quat.x, -quat.y, -quat.z, quat.w); const inorm2 = 1.0/(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w); quat.x *= inorm2; quat.y *= inorm2; quat.z *= inorm2; quat.w *= inorm2; return quat; } static qlerp(lhq, rhq, ratio) { var q = new Quaternion(0, 0, 0, 1); var qr = lhq.w * rhq.w + lhq.x * rhq.x + lhq.y * rhq.y + lhq.z * rhq.z; var ss = 1.0 - qr * qr; if (ss === 0.0) { q.w = lhq.w; q.x = lhq.x; q.y = lhq.y; q.z = lhq.z; return q; } else { if (qr > 1) { qr = 0.999; } else if (qr < -1) { qr = -0.999; } let ph = Math.acos(qr); let s2; if(qr < 0.0 && ph > Math.PI / 2.0){ qr = - lhq.w * rhq.w - lhq.x * rhq.x - lhq.y * rhq.y - lhq.z * rhq.z; ph = Math.acos(qr); s2 = -1 * Math.sin(ph * ratio) / Math.sin(ph); } else { s2 = Math.sin(ph * ratio) / Math.sin(ph); } let s1 = Math.sin(ph * (1.0 - ratio)) / Math.sin(ph); q.x = lhq.x * s1 + rhq.x * s2; q.y = lhq.y * s1 + rhq.y * s2; q.z = lhq.z * s1 + rhq.z * s2; q.w = lhq.w * s1 + rhq.w * s2; return q; } } axisAngle(axisVec3, angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var halfAngle = 0.5 * radian; var sin = Math.sin(halfAngle); var axis = Vector3.normalize(axisVec3); this.w = Math.cos(halfAngle); this.x = sin * axis.x; this.y = sin * axis.y; this.z = sin * axis.z; return this; } static axisAngle(axisVec3, angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var halfAngle = 0.5 * radian; var sin = Math.sin(halfAngle); var axis = Vector3.normalize(axisVec3); return new Quaternion( sin * axis.x, sin * axis.y, sin * axis.z, Math.cos(halfAngle)); } add(q) { this.x += q.x; this.y += q.y; this.z += q.z; this.w += q.w; return this; } multiply(q) { let result = new Quaternion(0, 0, 0, 1); result.x = q.w*this.x + q.z*this.y + q.y*this.z - q.x*this.w; result.y = - q.z*this.x + q.w*this.y + q.x*this.z - q.y*this.w; result.z = q.y*this.x + q.x*this.y + q.w*this.z - q.z*this.w; result.w = - q.x*this.x - q.y*this.y - q.z*this.z - q.w*this.w; this.x = result.x; this.y = result.y; this.z = result.z; this.w = result.w; return this; } static multiply(q1, q2) { let result = new Quaternion(0, 0, 0, 1); result.x = q2.w*q1.x + q2.z*q1.y - q2.y*q1.z + q2.x*q1.w; result.y = - q2.z*q1.x + q2.w*q1.y + q2.x*q1.z + q2.y*q1.w; result.z = q2.y*q1.x - q2.x*q1.y + q2.w*q1.z + q2.z*q1.w; result.w = - q2.x*q1.x - q2.y*q1.y - q2.z*q1.z + q2.w*q1.w; return result; } static fromMatrix(m) { let q = new Quaternion(); let tr = m.m00 + m.m11 + m.m22; if (tr > 0) { let S = 0.5 / Math.sqrt(tr+1.0); q.w = 0.25 / S; q.x = (m.m21 - m.m12) * S; q.y = (m.m02 - m.m20) * S; q.z = (m.m10 - m.m01) * S; } else if ((m.m00 > m.m11) && (m.m00 > m.m22)) { let S = Math.sqrt(1.0 + m.m00 - m.m11 - m.m22) * 2; q.w = (m.m21 - m.m12) / S; q.x = 0.25 * S; q.y = (m.m01 + m.m10) / S; q.z = (m.m02 + m.m20) / S; } else if (m.m11 > m.m22) { let S = Math.sqrt(1.0 + m.m11 - m.m00 - m.m22) * 2; q.w = (m.m02 - m.m20) / S; q.x = (m.m01 + m.m10) / S; q.y = 0.25 * S; q.z = (m.m12 + m.m21) / S; } else { let S = Math.sqrt(1.0 + m.m22 - m.m00 - m.m11) * 2; q.w = (m.m10 - m.m01) / S; q.x = (m.m02 + m.m20) / S; q.y = (m.m12 + m.m21) / S; q.z = 0.25 * S; } return q; } /* static fromMatrix(m) { let fTrace = m.m[0] + m.m[4] + m.m[8]; let fRoot; let q = new Quaternion(); if ( fTrace > 0.0 ) { // |w| > 1/2, may as well choose w > 1/2 fRoot = Math.sqrt(fTrace + 1.0); // 2w q.w = 0.5 * fRoot; fRoot = 0.5/fRoot; // 1/(4w) q.x = (m.m[5]-m.m[7])*fRoot; q.y = (m.m[6]-m.m[2])*fRoot; q.z = (m.m[1]-m.m[3])*fRoot; } else { // |w| <= 1/2 let i = 0; if ( m.m[4] > m.m[0] ) i = 1; if ( m.m[8] > m.m[i*3+i] ) i = 2; let j = (i+1)%3; let k = (i+2)%3; fRoot = Math.sqrt(m.m[i*3+i]-m.m[j*3+j]-m.m[k*3+k] + 1.0); let setValue = function(q, i, value) { switch (i) { case 0: q.x = value; break; case 1: q.y = value; break; case 2: q.z = value; break; } } setValue(q, i, 0.5 * fRoot); // q[i] = 0.5 * fRoot; fRoot = 0.5 / fRoot; q.w = (m.m[j*3+k] - m.m[k*3+j]) * fRoot; setValue(q, j, (m.m[j*3+i] + m.m[i*3+j]) * fRoot); // q[j] = (m.m[j*3+i] + m.m[i*3+j]) * fRoot; setValue(q, k, (m.m[k*3+i] + m.m[i*3+k]) * fRoot); // q[k] = (m.m[k*3+i] + m.m[i*3+k]) * fRoot; } return q; } */ static fromPosition(vec3) { let q = new Quaternion(vec3.x, vec3.y, vec3.z, 0); return q; } at(i) { switch (i%4) { case 0: return this.x; case 1: return this.y; case 2: return this.z; case 3: return this.w; } } setAt(i, val) { switch (i%4) { case 0: this.x = val; break; case 1: this.y = val; break; case 2: this.z = val; break; case 3: this.w = val; break; } } normalize() { let norm = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z + this.w*this.w); this.x /= norm; this.y /= norm; this.z /= norm; this.w /= norm; return this; } toString() { return '(' + this.x + ', ' + this.y + ', ' + this.z + ', ' + this.w + ')'; } } GLBoost$1["Quaternion"] = Quaternion; class Matrix33 { constructor(m, isColumnMajor = false, shaderParameterType = void 0, shaderParameterEntityIndex = void 0, shaderParameterName = void 0 ) { this.m = new Float32Array(9); // Data order is column major if (arguments.length >= 9) { if (isColumnMajor === true) { let m = arguments; this.setComponents( m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]); } else { this.setComponents.apply(this, arguments); // arguments[0-8] must be row major values if isColumnMajor is false } } else if (Array.isArray(m)) { if (isColumnMajor === true) { this.setComponents( m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]); } else { this.setComponents.apply(this, m); // 'm' must be row major array if isColumnMajor is false } } else if (m instanceof Float32Array) { if (isColumnMajor === true) { this.setComponents( m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]); } else { this.setComponents.apply(this, m); // 'm' must be row major array if isColumnMajor is false } } else if (!!m && typeof m.m22 !== 'undefined') { if (isColumnMajor === true) { this.setComponents( m.m00, m.m01, m.m02, m.m10, m.m11, m.m12, m.m20, m.m21, m.m22); } else { this.setComponents(m.m00, m.m01, m.m02, m.m10, m.m11, m.m12, m.m20, m.m21, m.m22); // 'm' must be row major array if isColumnMajor is false } } else if (!!m && typeof m.className !== 'undefined' && m.className === 'Quaternion') { const sx = m.x * m.x; const sy = m.y * m.y; const sz = m.z * m.z; const cx = m.y * m.z; const cy = m.x * m.z; const cz = m.x * m.y; const wx = m.w * m.x; const wy = m.w * m.y; const wz = m.w * m.z; this.setComponents( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy) ); } else { this.identity(); } } setComponents(m00, m01, m02, m10, m11, m12, m20, m21, m22) { this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m20 = m20; this.m21 = m21; this.m22 = m22; return this; } get className() { return this.constructor.name; } identity() { this.setComponents( 1, 0, 0, 0, 1, 0, 0, 0, 1 ); return this; } /** * Make this identity matrix(static method version) */ static identity() { return new Matrix33( 1, 0, 0, 0, 1, 0, 0, 0, 1 ); } clone() { return new Matrix33( this.m[0], this.m[3], this.m[6], this.m[1], this.m[4], this.m[7], this.m[2], this.m[5], this.m[8] ); } /** * Create X oriented Rotation Matrix */ rotateX(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return this.setComponents( 1, 0, 0, 0, cos, -sin, 0, sin, cos ); } /** * Create X oriented Rotation Matrix */ static rotateX(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix33( 1, 0, 0, 0, cos, -sin, 0, sin, cos ); } /** * Create Y oriented Rotation Matrix */ rotateY(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); this.setComponents( cos, 0, sin, 0, 1, 0, -sin, 0, cos ); return this; } /** * Create Y oriented Rotation Matrix */ static rotateY(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix33( cos, 0, sin, 0, 1, 0, -sin, 0, cos ); } /** * Create Z oriented Rotation Matrix */ rotateZ(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return this.setComponents( cos, -sin, 0, sin, cos, 0, 0, 0, 1 ); } /** * Create Z oriented Rotation Matrix */ static rotateZ(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix33( cos, -sin, 0, sin, cos, 0, 0, 0, 1 ); } static rotateXYZ(x, y, z) { return (Matrix33.rotateZ(z).multiply(Matrix33.rotateY(y).multiply(Matrix33.rotateX(x)))); } static rotate(vec3) { return (Matrix33.rotateZ(vec3.z).multiply(Matrix33.rotateY(vec3.y).multiply(Matrix33.rotateX(vec3.x)))); } scale(vec) { return this.setComponents( vec.x, 0, 0, 0, vec.y, 0, 0, 0, vec.z ); } static scale(vec) { return new Matrix33( vec.x, 0, 0, 0, vec.y, 0, 0, 0, vec.z ); } /** * zero matrix */ zero() { this.setComponents(0, 0, 0, 0, 0, 0, 0, 0, 0); return this; } /** * zero matrix(static version) */ static zero() { return new Matrix33(0, 0, 0, 0, 0, 0, 0, 0, 0); } flatten() { return this.m; } flattenAsArray() { return [this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5], this.m[6], this.m[7], this.m[8]]; } _swap(l, r) { this.m[r] = [this.m[l], this.m[l] = this.m[r]][0]; // Swap } /** * transpose */ transpose() { this._swap(1, 3); this._swap(2, 6); this._swap(5, 8); return this; } /** * transpose(static version) */ static transpose(mat) { var mat_t = new Matrix33( mat.m00, mat.m10, mat.m20, mat.m01, mat.m11, mat.m21, mat.m02, mat.m12, mat.m22 ); return mat_t; } multiplyVector(vec) { var x = this.m00*vec.x + this.m01*vec.y + this.m02*vec.z; var y = this.m10*vec.x + this.m11*vec.y + this.m12*vec.z; var z = this.m20*vec.x + this.m21*vec.y + this.m22*vec.z; return new Vector3(x, y, z); } /** * multiply zero matrix and zero matrix */ multiply(mat) { var m00 = this.m00*mat.m00 + this.m01*mat.m10 + this.m02*mat.m20; var m01 = this.m00*mat.m01 + this.m01*mat.m11 + this.m02*mat.m21; var m02 = this.m00*mat.m02 + this.m01*mat.m12 + this.m02*mat.m22; var m10 = this.m10*mat.m00 + this.m11*mat.m10 + this.m12*mat.m20; var m11 = this.m10*mat.m01 + this.m11*mat.m11 + this.m12*mat.m21; var m12 = this.m10*mat.m02 + this.m11*mat.m12 + this.m12*mat.m22; var m20 = this.m20*mat.m00 + this.m21*mat.m10 + this.m22*mat.m20; var m21 = this.m20*mat.m01 + this.m21*mat.m11 + this.m22*mat.m21; var m22 = this.m20*mat.m02 + this.m21*mat.m12 + this.m22*mat.m22; return this.setComponents( m00, m01, m02, m10, m11, m12, m20, m21, m22 ); } /** * multiply zero matrix and zero matrix(static version) */ static multiply(l_m, r_m) { var m00 = l_m.m00*r_m.m00 + l_m.m01*r_m.m10 + l_m.m02*r_m.m20; var m10 = l_m.m10*r_m.m00 + l_m.m11*r_m.m10 + l_m.m12*r_m.m20; var m20 = l_m.m20*r_m.m00 + l_m.m21*r_m.m10 + l_m.m22*r_m.m20; var m01 = l_m.m00*r_m.m01 + l_m.m01*r_m.m11 + l_m.m02*r_m.m21; var m11 = l_m.m10*r_m.m01 + l_m.m11*r_m.m11 + l_m.m12*r_m.m21; var m21 = l_m.m20*r_m.m01 + l_m.m21*r_m.m11 + l_m.m22*r_m.m21; var m02 = l_m.m00*r_m.m02 + l_m.m01*r_m.m12 + l_m.m02*r_m.m22; var m12 = l_m.m10*r_m.m02 + l_m.m11*r_m.m12 + l_m.m12*r_m.m22; var m22 = l_m.m20*r_m.m02 + l_m.m21*r_m.m12 + l_m.m22*r_m.m22; return new Matrix33( m00, m01, m02, m10, m11, m12, m20, m21, m22 ); } determinant() { return this.m00*this.m11*this.m22 + this.m10*this.m21*this.m02 + this.m20*this.m01*this.m12 - this.m00*this.m21*this.m12 - this.m20*this.m11*this.m02 - this.m10*this.m01*this.m22; } static determinant(mat) { return mat.m00*mat.m11*mat.m22 + mat.m10*mat.m21*mat.m02 + mat.m20*mat.m01*mat.m12 - mat.m00*mat.m21*mat.m12 - mat.m20*mat.m11*mat.m02 - mat.m10*mat.m01*mat.m22; } invert() { var det = this.determinant(); var m00 = (this.m11*this.m22 - this.m12*this.m21) / det; var m01 = (this.m02*this.m21 - this.m01*this.m22) / det; var m02 = (this.m01*this.m12 - this.m02*this.m11) / det; var m10 = (this.m12*this.m20 - this.m10*this.m22) / det; var m11 = (this.m00*this.m22 - this.m02*this.m20) / det; var m12 = (this.m02*this.m10 - this.m00*this.m12) / det; var m20 = (this.m10*this.m21 - this.m11*this.m20) / det; var m21 = (this.m01*this.m20 - this.m00*this.m21) / det; var m22 = (this.m00*this.m11 - this.m01*this.m10) / det; return this.setComponents( m00, m01, m02, m10, m11, m12, m20, m21, m22 ); } static invert(mat) { var det = mat.determinant(); var m00 = (mat.m11*mat.m22 - mat.m12*mat.m21) / det; var m01 = (mat.m02*mat.m21 - mat.m01*mat.m22) / det; var m02 = (mat.m01*mat.m12 - mat.m02*mat.m11) / det; var m10 = (mat.m12*mat.m20 - mat.m10*mat.m22) / det; var m11 = (mat.m00*mat.m22 - mat.m02*mat.m20) / det; var m12 = (mat.m02*mat.m10 - mat.m00*mat.m12) / det; var m20 = (mat.m10*mat.m21 - mat.m11*mat.m20) / det; var m21 = (mat.m01*mat.m20 - mat.m00*mat.m21) / det; var m22 = (mat.m00*mat.m11 - mat.m01*mat.m10) / det; return new Matrix33( m00, m01, m02, m10, m11, m12, m20, m21, m22 ); } set m00(val) { this.m[0] = val; } get m00() { return this.m[0]; } set m10(val) { this.m[1] = val; } get m10() { return this.m[1]; } set m20(val) { this.m[2] = val; } get m20() { return this.m[2]; } set m01(val) { this.m[3] = val; } get m01() { return this.m[3]; } set m11(val) { this.m[4] = val; } get m11() { return this.m[4]; } set m21(val) { this.m[5] = val; } get m21() { return this.m[5]; } set m02(val) { this.m[6] = val; } get m02() { return this.m[6]; } set m12(val) { this.m[7] = val; } get m12() { return this.m[7]; } set m22(val) { this.m[8] = val; } get m22() { return this.m[8]; } toString() { return this.m00 + ' ' + this.m01 + ' ' + this.m02 + '\n' + this.m10 + ' ' + this.m11 + ' ' + this.m12 + '\n' + this.m20 + ' ' + this.m21 + ' ' + this.m22 + '\n'; } nearZeroToZero(value) { if (Math.abs(value) < 0.00001) { value = 0; } else if (0.99999 < value && value < 1.00001) { value = 1; } else if (-1.00001 < value && value < -0.99999) { value = -1; } return value; } toStringApproximately() { return this.nearZeroToZero(this.m00) + ' ' + this.nearZeroToZero(this.m01) + ' ' + this.nearZeroToZero(this.m02) + '\n' + this.nearZeroToZero(this.m10) + ' ' + this.nearZeroToZero(this.m11) + ' ' + this.nearZeroToZero(this.m12) + ' \n' + this.nearZeroToZero(this.m20) + ' ' + this.nearZeroToZero(this.m21) + ' ' + this.nearZeroToZero(this.m22) + '\n'; } getScale() { return new Vector3( Math.sqrt(this.m00 * this.m00 + this.m01 * this.m01 + this.m02 * this.m02), Math.sqrt(this.m10 * this.m10 + this.m11 * this.m11 + this.m12 * this.m12), Math.sqrt(this.m20 * this.m20 + this.m21 * this.m21 + this.m22 * this.m22) ); } addScale(vec) { this.m00 *= vec.x; this.m11 *= vec.y; this.m22 *= vec.z; return this; } } GLBoost$1['Matrix33'] = Matrix33; class Matrix44$1 { constructor(m, isColumnMajor = false, notCopyFloat32Array = false ) { if (arguments.length >= 16) { this.m = new Float32Array(16); // Data order is column major if (isColumnMajor === true) { let m = arguments; this.setComponents( m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); } else { this.setComponents.apply(this, arguments); // arguments[0-15] must be row major values if isColumnMajor is false } } else if (Array.isArray(m)) { this.m = new Float32Array(16); if (isColumnMajor === true) { this.setComponents( m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); } else { this.setComponents.apply(this, m); // 'm' must be row major array if isColumnMajor is false } } else if (m instanceof Float32Array) { if (notCopyFloat32Array) { this.m = m; } else { this.m = new Float32Array(16); if (isColumnMajor === true) { this.setComponents( m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]); } else { this.setComponents.apply(this, m); // 'm' must be row major array if isColumnMajor is false } } } else if (!!m && typeof m.m33 === 'undefined' && typeof m.m22 !== 'undefined') { if (notCopyFloat32Array) { this.m = m.m; } else { this.m = new Float32Array(16); if (isColumnMajor === true) { this.setComponents( m.m00, m.m01, m.m02, 0, m.m10, m.m11, m.m12, 0, m.m20, m.m21, m.m22, 0, 0, 0, 0, 1); } else { this.setComponents(m.m00, m.m01, m.m02, 0, m.m10, m.m11, m.m12, 0, m.m20, m.m21, m.m22, 0, 0, 0, 0, 1); // 'm' must be row major array if isColumnMajor is false } } } else if (!!m && typeof m.className !== 'undefined' && m.className === 'Quaternion') { this.m = new Float32Array(16); const sx = m.x * m.x; const sy = m.y * m.y; const sz = m.z * m.z; const cx = m.y * m.z; const cy = m.x * m.z; const cz = m.x * m.y; const wx = m.w * m.x; const wy = m.w * m.y; const wz = m.w * m.z; this.setComponents( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), 0.0, 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), 0.0, 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy), 0.0, 0.0, 0.0, 0.0, 1.0 ); } else { this.m = new Float32Array(16); this.identity(); } } setComponents(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; return this; } copyComponents(mat4) { //this.m.set(mat4.m); this.setComponents.apply(this, mat4.m); // 'm' must be row major array if isColumnMajor is false } get className() { return this.constructor.name; } clone() { return new Matrix44$1( this.m[0], this.m[4], this.m[8], this.m[12], this.m[1], this.m[5], this.m[9], this.m[13], this.m[2], this.m[6], this.m[10], this.m[14], this.m[3], this.m[7], this.m[11], this.m[15] ); } /** * to the identity matrix */ identity() { this.setComponents( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); return this; } /** * to the identity matrix(static版) */ static identity() { return new Matrix44$1( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); } translate(vec) { return this.setComponents( 1, 0, 0, vec.x, 0, 1, 0, vec.y, 0, 0, 1, vec.z, 0, 0, 0, 1 ); } putTranslate(vec) { this.m03 = vec.x; this.m13 = vec.y; this.m23 = vec.z; } getTranslate() { return new Vector3(this.m03, this.m13, this.m23); } static translate(vec) { return new Matrix44$1( 1, 0, 0, vec.x, 0, 1, 0, vec.y, 0, 0, 1, vec.z, 0, 0, 0, 1 ); } scale(vec) { return this.setComponents( vec.x, 0, 0, 0, 0, vec.y, 0, 0, 0, 0, vec.z, 0, 0, 0, 0, 1 ); } static scale(vec) { return new Matrix44$1( vec.x, 0, 0, 0, 0, vec.y, 0, 0, 0, 0, vec.z, 0, 0, 0, 0, 1 ); } addScale(vec) { this.m00 *= vec.x; this.m11 *= vec.y; this.m22 *= vec.z; return this; } /** * Create X oriented Rotation Matrix */ rotateX(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return this.setComponents( 1, 0, 0, 0, 0, cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1 ); } /** * Create X oriented Rotation Matrix */ static rotateX(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix44$1( 1, 0, 0, 0, 0, cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1 ); } /** * Create Y oriented Rotation Matrix */ rotateY(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return this.setComponents( cos, 0, sin, 0, 0, 1, 0, 0, -sin, 0, cos, 0, 0, 0, 0, 1 ); } /** * Create Y oriented Rotation Matrix */ static rotateY(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix44$1( cos, 0, sin, 0, 0, 1, 0, 0, -sin, 0, cos, 0, 0, 0, 0, 1 ); } /** * Create Z oriented Rotation Matrix */ rotateZ(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return this.setComponents( cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); } /** * Create Z oriented Rotation Matrix */ static rotateZ(angle) { var radian = 0; if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { radian = MathUtil.degreeToRadian(angle); } else { radian = angle; } var cos = Math.cos(radian); var sin = Math.sin(radian); return new Matrix44$1( cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); } static rotateXYZ(x, y, z) { return new Matrix44$1(Matrix33.rotateZ(z).multiply(Matrix33.rotateY(y).multiply(Matrix33.rotateX(x)))); } /** * @return Euler Angles Rotation (x, y, z) */ toEulerAngles() { let rotate = null; if (Math.abs(this.m20) != 1.0) { let y = -Math.asin(this.m20); let x = Math.atan2(this.m21 / Math.cos(y), this.m22 / Math.cos(y)); let z = Math.atan2(this.m10 / Math.cos(y), this.m00 / Math.cos(y)); rotate = new Vector3(x, y, z); } else if (this.m20 === -1.0) { rotate = new Vector3(Math.atan2(this.m01, this.m02), Math.PI/2.0, 0.0); } else { rotate = new Vector3(Math.atan2(-this.m01, -this.m02), -Math.PI/2.0, 0.0); } if (GLBoost$1["VALUE_ANGLE_UNIT"] === GLBoost$1.DEGREE) { rotate.x = MathUtil.radianToDegree(rotate.x); rotate.y = MathUtil.radianToDegree(rotate.y); rotate.z = MathUtil.radianToDegree(rotate.z); } return rotate; } /** * ゼロ行列 */ zero() { this.setComponents(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return this; } static zero() { return new Matrix44$1(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } flatten() { return this.m; } flattenAsArray() { return [this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5], this.m[6], this.m[7], this.m[8], this.m[9], this.m[10], this.m[11], this.m[12], this.m[13], this.m[14], this.m[15]]; } _swap(l, r) { this.m[r] = [this.m[l], this.m[l] = this.m[r]][0]; // Swap } /** * transpose */ transpose() { this._swap(1, 4); this._swap(2, 8); this._swap(3, 12); this._swap(6, 9); this._swap(7, 13); this._swap(11, 14); return this; } /** * transpose(static version) */ static transpose(mat) { var mat_t = new Matrix44$1( mat.m00, mat.m10, mat.m20, mat.m30, mat.m01, mat.m11, mat.m21, mat.m31, mat.m02, mat.m12, mat.m22, mat.m32, mat.m03, mat.m13, mat.m23, mat.m33 ); return mat_t; } multiplyVector(vec) { var x = this.m00*vec.x + this.m01*vec.y + this.m02*vec.z + this.m03*vec.w; var y = this.m10*vec.x + this.m11*vec.y + this.m12*vec.z + this.m13*vec.w; var z = this.m20*vec.x + this.m21*vec.y + this.m22*vec.z + this.m23*vec.w; var w = this.m30*vec.x + this.m31*vec.y + this.m32*vec.z + this.m33*vec.w; return new Vector4$1(x, y, z, w); } /** * multiply zero matrix and zero matrix */ multiply(mat) { var m00 = this.m00*mat.m00 + this.m01*mat.m10 + this.m02*mat.m20 + this.m03*mat.m30; var m01 = this.m00*mat.m01 + this.m01*mat.m11 + this.m02*mat.m21 + this.m03*mat.m31; var m02 = this.m00*mat.m02 + this.m01*mat.m12 + this.m02*mat.m22 + this.m03*mat.m32; var m03 = this.m00*mat.m03 + this.m01*mat.m13 + this.m02*mat.m23 + this.m03*mat.m33; var m10 = this.m10*mat.m00 + this.m11*mat.m10 + this.m12*mat.m20 + this.m13*mat.m30; var m11 = this.m10*mat.m01 + this.m11*mat.m11 + this.m12*mat.m21 + this.m13*mat.m31; var m12 = this.m10*mat.m02 + this.m11*mat.m12 + this.m12*mat.m22 + this.m13*mat.m32; var m13 = this.m10*mat.m03 + this.m11*mat.m13 + this.m12*mat.m23 + this.m13*mat.m33; var m20 = this.m20*mat.m00 + this.m21*mat.m10 + this.m22*mat.m20 + this.m23*mat.m30; var m21 = this.m20*mat.m01 + this.m21*mat.m11 + this.m22*mat.m21 + this.m23*mat.m31; var m22 = this.m20*mat.m02 + this.m21*mat.m12 + this.m22*mat.m22 + this.m23*mat.m32; var m23 = this.m20*mat.m03 + this.m21*mat.m13 + this.m22*mat.m23 + this.m23*mat.m33; var m30 = this.m30*mat.m00 + this.m31*mat.m10 + this.m32*mat.m20 + this.m33*mat.m30; var m31 = this.m30*mat.m01 + this.m31*mat.m11 + this.m32*mat.m21 + this.m33*mat.m31; var m32 = this.m30*mat.m02 + this.m31*mat.m12 + this.m32*mat.m22 + this.m33*mat.m32; var m33 = this.m30*mat.m03 + this.m31*mat.m13 + this.m32*mat.m23 + this.m33*mat.m33; return this.setComponents( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); } multiplyByLeft(mat) { var m00 = mat.m00*this.m00 + mat.m01*this.m10 + mat.m02*this.m20 + mat.m03*this.m30; var m01 = mat.m00*this.m01 + mat.m01*this.m11 + mat.m02*this.m21 + mat.m03*this.m31; var m02 = mat.m00*this.m02 + mat.m01*this.m12 + mat.m02*this.m22 + mat.m03*this.m32; var m03 = mat.m00*this.m03 + mat.m01*this.m13 + mat.m02*this.m23 + mat.m03*this.m33; var m10 = mat.m10*this.m00 + mat.m11*this.m10 + mat.m12*this.m20 + mat.m13*this.m30; var m11 = mat.m10*this.m01 + mat.m11*this.m11 + mat.m12*this.m21 + mat.m13*this.m31; var m12 = mat.m10*this.m02 + mat.m11*this.m12 + mat.m12*this.m22 + mat.m13*this.m32; var m13 = mat.m10*this.m03 + mat.m11*this.m13 + mat.m12*this.m23 + mat.m13*this.m33; var m20 = mat.m20*this.m00 + mat.m21*this.m10 + mat.m22*this.m20 + mat.m23*this.m30; var m21 = mat.m20*this.m01 + mat.m21*this.m11 + mat.m22*this.m21 + mat.m23*this.m31; var m22 = mat.m20*this.m02 + mat.m21*this.m12 + mat.m22*this.m22 + mat.m23*this.m32; var m23 = mat.m20*this.m03 + mat.m21*this.m13 + mat.m22*this.m23 + mat.m23*this.m33; var m30 = mat.m30*this.m00 + mat.m31*this.m10 + mat.m32*this.m20 + mat.m33*this.m30; var m31 = mat.m30*this.m01 + mat.m31*this.m11 + mat.m32*this.m21 + mat.m33*this.m31; var m32 = mat.m30*this.m02 + mat.m31*this.m12 + mat.m32*this.m22 + mat.m33*this.m32; var m33 = mat.m30*this.m03 + mat.m31*this.m13 + mat.m32*this.m23 + mat.m33*this.m33; return this.setComponents( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); } /** * multiply zero matrix and zero matrix(static version) */ static multiply(l_m, r_m) { var m00 = l_m.m00*r_m.m00 + l_m.m01*r_m.m10 + l_m.m02*r_m.m20 + l_m.m03*r_m.m30; var m10 = l_m.m10*r_m.m00 + l_m.m11*r_m.m10 + l_m.m12*r_m.m20 + l_m.m13*r_m.m30; var m20 = l_m.m20*r_m.m00 + l_m.m21*r_m.m10 + l_m.m22*r_m.m20 + l_m.m23*r_m.m30; var m30 = l_m.m30*r_m.m00 + l_m.m31*r_m.m10 + l_m.m32*r_m.m20 + l_m.m33*r_m.m30; var m01 = l_m.m00*r_m.m01 + l_m.m01*r_m.m11 + l_m.m02*r_m.m21 + l_m.m03*r_m.m31; var m11 = l_m.m10*r_m.m01 + l_m.m11*r_m.m11 + l_m.m12*r_m.m21 + l_m.m13*r_m.m31; var m21 = l_m.m20*r_m.m01 + l_m.m21*r_m.m11 + l_m.m22*r_m.m21 + l_m.m23*r_m.m31; var m31 = l_m.m30*r_m.m01 + l_m.m31*r_m.m11 + l_m.m32*r_m.m21 + l_m.m33*r_m.m31; var m02 = l_m.m00*r_m.m02 + l_m.m01*r_m.m12 + l_m.m02*r_m.m22 + l_m.m03*r_m.m32; var m12 = l_m.m10*r_m.m02 + l_m.m11*r_m.m12 + l_m.m12*r_m.m22 + l_m.m13*r_m.m32; var m22 = l_m.m20*r_m.m02 + l_m.m21*r_m.m12 + l_m.m22*r_m.m22 + l_m.m23*r_m.m32; var m32 = l_m.m30*r_m.m02 + l_m.m31*r_m.m12 + l_m.m32*r_m.m22 + l_m.m33*r_m.m32; var m03 = l_m.m00*r_m.m03 + l_m.m01*r_m.m13 + l_m.m02*r_m.m23 + l_m.m03*r_m.m33; var m13 = l_m.m10*r_m.m03 + l_m.m11*r_m.m13 + l_m.m12*r_m.m23 + l_m.m13*r_m.m33; var m23 = l_m.m20*r_m.m03 + l_m.m21*r_m.m13 + l_m.m22*r_m.m23 + l_m.m23*r_m.m33; var m33 = l_m.m30*r_m.m03 + l_m.m31*r_m.m13 + l_m.m32*r_m.m23 + l_m.m33*r_m.m33; return new Matrix44$1( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); } determinant() { return this.m00*this.m11*this.m22*this.m33 + this.m00*this.m12*this.m23*this.m31 + this.m00*this.m13*this.m21*this.m32 + this.m01*this.m10*this.m23*this.m32 + this.m01*this.m12*this.m20*this.m33 + this.m01*this.m13*this.m22*this.m30 + this.m02*this.m10*this.m21*this.m33 + this.m02*this.m11*this.m23*this.m30 + this.m02*this.m13*this.m20*this.m31 + this.m03*this.m10*this.m22*this.m31 + this.m03*this.m11*this.m20*this.m32 + this.m03*this.m12*this.m21*this.m30 - this.m00*this.m11*this.m23*this.m32 - this.m00*this.m12*this.m21*this.m33 - this.m00*this.m13*this.m22*this.m31 - this.m01*this.m10*this.m22*this.m33 - this.m01*this.m12*this.m23*this.m30 - this.m01*this.m13*this.m20*this.m32 - this.m02*this.m10*this.m23*this.m31 - this.m02*this.m11*this.m20*this.m33 - this.m02*this.m13*this.m21*this.m30 - this.m03*this.m10*this.m21*this.m32 - this.m03*this.m11*this.m22*this.m30 - this.m03*this.m12*this.m20*this.m31; } static determinant(mat) { return mat.m00*mat.m11*mat.m22*mat.m33 + mat.m00*mat.m12*mat.m23*mat.m31 + mat.m00*mat.m13*mat.m21*mat.m32 + mat.m01*mat.m10*mat.m23*mat.m32 + mat.m01*mat.m12*mat.m20*mat.m33 + mat.m01*mat.m13*mat.m22*mat.m30 + mat.m02*mat.m10*mat.m21*mat.m33 + mat.m02*mat.m11*mat.m23*mat.m30 + mat.m02*mat.m13*mat.m20*mat.m31 + mat.m03*mat.m10*mat.m22*mat.m31 + mat.m03*mat.m11*mat.m20*mat.m32 + mat.m03*mat.m12*mat.m21*mat.m30 - mat.m00*mat.m11*mat.m23*mat.m32 - mat.m00*mat.m12*mat.m21*mat.m33 - mat.m00*mat.m13*mat.m22*mat.m31 - mat.m01*mat.m10*mat.m22*mat.m33 - mat.m01*mat.m12*mat.m23*mat.m30 - mat.m01*mat.m13*mat.m20*mat.m32 - mat.m02*mat.m10*mat.m23*mat.m31 - mat.m02*mat.m11*mat.m20*mat.m33 - mat.m02*mat.m13*mat.m21*mat.m30 - mat.m03*mat.m10*mat.m21*mat.m32 - mat.m03*mat.m11*mat.m22*mat.m30 - mat.m03*mat.m12*mat.m20*mat.m31; } invert() { var det = this.determinant(); var m00 = (this.m11*this.m22*this.m33 + this.m12*this.m23*this.m31 + this.m13*this.m21*this.m32 - this.m11*this.m23*this.m32 - this.m12*this.m21*this.m33 - this.m13*this.m22*this.m31) / det; var m01 = (this.m01*this.m23*this.m32 + this.m02*this.m21*this.m33 + this.m03*this.m22*this.m31 - this.m01*this.m22*this.m33 - this.m02*this.m23*this.m31 - this.m03*this.m21*this.m32) / det; var m02 = (this.m01*this.m12*this.m33 + this.m02*this.m13*this.m31 + this.m03*this.m11*this.m32 - this.m01*this.m13*this.m32 - this.m02*this.m11*this.m33 - this.m03*this.m12*this.m31) / det; var m03 = (this.m01*this.m13*this.m22 + this.m02*this.m11*this.m23 + this.m03*this.m12*this.m21 - this.m01*this.m12*this.m23 - this.m02*this.m13*this.m21 - this.m03*this.m11*this.m22) / det; var m10 = (this.m10*this.m23*this.m32 + this.m12*this.m20*this.m33 + this.m13*this.m22*this.m30 - this.m10*this.m22*this.m33 - this.m12*this.m23*this.m30 - this.m13*this.m20*this.m32) / det; var m11 = (this.m00*this.m22*this.m33 + this.m02*this.m23*this.m30 + this.m03*this.m20*this.m32 - this.m00*this.m23*this.m32 - this.m02*this.m20*this.m33 - this.m03*this.m22*this.m30) / det; var m12 = (this.m00*this.m13*this.m32 + this.m02*this.m10*this.m33 + this.m03*this.m12*this.m30 - this.m00*this.m12*this.m33 - this.m02*this.m13*this.m30 - this.m03*this.m10*this.m32) / det; var m13 = (this.m00*this.m12*this.m23 + this.m02*this.m13*this.m20 + this.m03*this.m10*this.m22 - this.m00*this.m13*this.m22 - this.m02*this.m10*this.m23 - this.m03*this.m12*this.m20) / det; var m20 = (this.m10*this.m21*this.m33 + this.m11*this.m23*this.m30 + this.m13*this.m20*this.m31 - this.m10*this.m23*this.m31 - this.m11*this.m20*this.m33 - this.m13*this.m21*this.m30) / det; var m21 = (this.m00*this.m23*this.m31 + this.m01*this.m20*this.m33 + this.m03*this.m21*this.m30 - this.m00*this.m21*this.m33 - this.m01*this.m23*this.m30 - this.m03*this.m20*this.m31) / det; var m22 = (this.m00*this.m11*this.m33 + this.m01*this.m13*this.m30 + this.m03*this.m10*this.m31 - this.m00*this.m13*this.m31 - this.m01*this.m10*this.m33 - this.m03*this.m11*this.m30) / det; var m23 = (this.m00*this.m13*this.m21 + this.m01*this.m10*this.m23 + this.m03*this.m11*this.m20 - this.m00*this.m11*this.m23 - this.m01*this.m13*this.m20 - this.m03*this.m10*this.m21) / det; var m30 = (this.m10*this.m22*this.m31 + this.m11*this.m20*this.m32 + this.m12*this.m21*this.m30 - this.m10*this.m21*this.m32 - this.m11*this.m22*this.m30 - this.m12*this.m20*this.m31) / det; var m31 = (this.m00*this.m21*this.m32 + this.m01*this.m22*this.m30 + this.m02*this.m20*this.m31 - this.m00*this.m22*this.m31 - this.m01*this.m20*this.m32 - this.m02*this.m21*this.m30) / det; var m32 = (this.m00*this.m12*this.m31 + this.m01*this.m10*this.m32 + this.m02*this.m11*this.m30 - this.m00*this.m11*this.m32 - this.m01*this.m12*this.m30 - this.m02*this.m10*this.m31) / det; var m33 = (this.m00*this.m11*this.m22 + this.m01*this.m12*this.m20 + this.m02*this.m10*this.m21 - this.m00*this.m12*this.m21 - this.m01*this.m10*this.m22 - this.m02*this.m11*this.m20) / det; return this.setComponents( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); } static invert(mat) { var det = mat.determinant(); var m00 = (mat.m11*mat.m22*mat.m33 + mat.m12*mat.m23*mat.m31 + mat.m13*mat.m21*mat.m32 - mat.m11*mat.m23*mat.m32 - mat.m12*mat.m21*mat.m33 - mat.m13*mat.m22*mat.m31) / det; var m01 = (mat.m01*mat.m23*mat.m32 + mat.m02*mat.m21*mat.m33 + mat.m03*mat.m22*mat.m31 - mat.m01*mat.m22*mat.m33 - mat.m02*mat.m23*mat.m31 - mat.m03*mat.m21*mat.m32) / det; var m02 = (mat.m01*mat.m12*mat.m33 + mat.m02*mat.m13*mat.m31 + mat.m03*mat.m11*mat.m32 - mat.m01*mat.m13*mat.m32 - mat.m02*mat.m11*mat.m33 - mat.m03*mat.m12*mat.m31) / det; var m03 = (mat.m01*mat.m13*mat.m22 + mat.m02*mat.m11*mat.m23 + mat.m03*mat.m12*mat.m21 - mat.m01*mat.m12*mat.m23 - mat.m02*mat.m13*mat.m21 - mat.m03*mat.m11*mat.m22) / det; var m10 = (mat.m10*mat.m23*mat.m32 + mat.m12*mat.m20*mat.m33 + mat.m13*mat.m22*mat.m30 - mat.m10*mat.m22*mat.m33 - mat.m12*mat.m23*mat.m30 - mat.m13*mat.m20*mat.m32) / det; var m11 = (mat.m00*mat.m22*mat.m33 + mat.m02*mat.m23*mat.m30 + mat.m03*mat.m20*mat.m32 - mat.m00*mat.m23*mat.m32 - mat.m02*mat.m20*mat.m33 - mat.m03*mat.m22*mat.m30) / det; var m12 = (mat.m00*mat.m13*mat.m32 + mat.m02*mat.m10*mat.m33 + mat.m03*mat.m12*mat.m30 - mat.m00*mat.m12*mat.m33 - mat.m02*mat.m13*mat.m30 - mat.m03*mat.m10*mat.m32) / det; var m13 = (mat.m00*mat.m12*mat.m23 + mat.m02*mat.m13*mat.m20 + mat.m03*mat.m10*mat.m22 - mat.m00*mat.m13*mat.m22 - mat.m02*mat.m10*mat.m23 - mat.m03*mat.m12*mat.m20) / det; var m20 = (mat.m10*mat.m21*mat.m33 + mat.m11*mat.m23*mat.m30 + mat.m13*mat.m20*mat.m31 - mat.m10*mat.m23*mat.m31 - mat.m11*mat.m20*mat.m33 - mat.m13*mat.m21*mat.m30) / det; var m21 = (mat.m00*mat.m23*mat.m31 + mat.m01*mat.m20*mat.m33 + mat.m03*mat.m21*mat.m30 - mat.m00*mat.m21*mat.m33 - mat.m01*mat.m23*mat.m30 - mat.m03*mat.m20*mat.m31) / det; var m22 = (mat.m00*mat.m11*mat.m33 + mat.m01*mat.m13*mat.m30 + mat.m03*mat.m10*mat.m31 - mat.m00*mat.m13*mat.m31 - mat.m01*mat.m10*mat.m33 - mat.m03*mat.m11*mat.m30) / det; var m23 = (mat.m00*mat.m13*mat.m21 + mat.m01*mat.m10*mat.m23 + mat.m03*mat.m11*mat.m20 - mat.m00*mat.m11*mat.m23 - mat.m01*mat.m13*mat.m20 - mat.m03*mat.m10*mat.m21) / det; var m30 = (mat.m10*mat.m22*mat.m31 + mat.m11*mat.m20*mat.m32 + mat.m12*mat.m21*mat.m30 - mat.m10*mat.m21*mat.m32 - mat.m11*mat.m22*mat.m30 - mat.m12*mat.m20*mat.m31) / det; var m31 = (mat.m00*mat.m21*mat.m32 + mat.m01*mat.m22*mat.m30 + mat.m02*mat.m20*mat.m31 - mat.m00*mat.m22*mat.m31 - mat.m01*mat.m20*mat.m32 - mat.m02*mat.m21*mat.m30) / det; var m32 = (mat.m00*mat.m12*mat.m31 + mat.m01*mat.m10*mat.m32 + mat.m02*mat.m11*mat.m30 - mat.m00*mat.m11*mat.m32 - mat.m01*mat.m12*mat.m30 - mat.m02*mat.m10*mat.m31) / det; var m33 = (mat.m00*mat.m11*mat.m22 + mat.m01*mat.m12*mat.m20 + mat.m02*mat.m10*mat.m21 - mat.m00*mat.m12*mat.m21 - mat.m01*mat.m10*mat.m22 - mat.m02*mat.m11*mat.m20) / det; return new Matrix44$1( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); } set m00(val) { this.m[0] = val; } get m00() { return this.m[0]; } set m10(val) { this.m[1] = val; } get m10() { return this.m[1]; } set m20(val) { this.m[2] = val; } get m20() { return this.m[2]; } set m30(val) { this.m[3] = val; } get m30() { return this.m[3]; } set m01(val) { this.m[4] = val; } get m01() { return this.m[4]; } set m11(val) { this.m[5] = val; } get m11() { return this.m[5]; } set m21(val) { this.m[6] = val; } get m21() { return this.m[6]; } set m31(val) { this.m[7] = val; } get m31() { return this.m[7]; } set m02(val) { this.m[8] = val; } get m02() { return this.m[8]; } set m12(val) { this.m[9] = val; } get m12() { return this.m[9]; } set m22(val) { this.m[10] = val; } get m22() { return this.m[10]; } set m32(val) { this.m[11] = val; } get m32() { return this.m[11]; } set m03(val) { this.m[12] = val; } get m03() { return this.m[12]; } set m13(val) { this.m[13] = val; } get m13() { return this.m[13]; } set m23(val) { this.m[14] = val; } get m23() { return this.m[14]; } set m33(val) { this.m[15] = val; } get m33() { return this.m[15]; } toString() { return this.m00 + ' ' + this.m01 + ' ' + this.m02 + ' ' + this.m03 + ' \n' + this.m10 + ' ' + this.m11 + ' ' + this.m12 + ' ' + this.m13 + ' \n' + this.m20 + ' ' + this.m21 + ' ' + this.m22 + ' ' + this.m23 + ' \n' + this.m30 + ' ' + this.m31 + ' ' + this.m32 + ' ' + this.m33 + ' \n'; } nearZeroToZero(value) { if (Math.abs(value) < 0.00001) { value = 0; } else if (0.99999 < value && value < 1.00001) { value = 1; } else if (-1.00001 < value && value < -0.99999) { value = -1; } return value; } toStringApproximately() { return this.nearZeroToZero(this.m00) + ' ' + this.nearZeroToZero(this.m01) + ' ' + this.nearZeroToZero(this.m02) + ' ' + this.nearZeroToZero(this.m03) + ' \n' + this.nearZeroToZero(this.m10) + ' ' + this.nearZeroToZero(this.m11) + ' ' + this.nearZeroToZero(this.m12) + ' ' + this.nearZeroToZero(this.m13) + ' \n' + this.nearZeroToZero(this.m20) + ' ' + this.nearZeroToZero(this.m21) + ' ' + this.nearZeroToZero(this.m22) + ' ' + this.nearZeroToZero(this.m23) + ' \n' + this.nearZeroToZero(this.m30) + ' ' + this.nearZeroToZero(this.m31) + ' ' + this.nearZeroToZero(this.m32) + ' ' + this.nearZeroToZero(this.m33) + ' \n'; } getScale() { return new Vector3( Math.sqrt(this.m00 * this.m00 + this.m01 * this.m01 + this.m02 * this.m02), Math.sqrt(this.m10 * this.m10 + this.m11 * this.m11 + this.m12 * this.m12), Math.sqrt(this.m20 * this.m20 + this.m21 * this.m21 + this.m22 * this.m22) ); } getRotate() { const quat = Quaternion.fromMatrix(this); const rotateMat = new Matrix44$1(quat); return rotateMat; } } GLBoost$1["Matrix44"] = Matrix44$1; // class MathClassUtil { constructor() { } static arrayToVector(element) { if (Array.isArray(element)) { if(typeof(element[3]) !== 'undefined') { return new Vector4$1(element[0], element[1], element[2], element[3]); } else if (typeof(element[2]) !== 'undefined') { return new Vector3(element[0], element[1], element[2]); } else { return new Vector2(element[0], element[1]); } } else { return element; } } static arrayToVectorOrMatrix(element) { if (Array.isArray(element)) { if(typeof(element[15]) !== 'undefined') { return new Matrix44$1(element); } else if(typeof(element[8]) !== 'undefined') { return new Matrix33(element); } else if(typeof(element[3]) !== 'undefined') { return new Vector4$1(element[0], element[1], element[2], element[3]); } else if (typeof(element[2]) !== 'undefined') { return new Vector3(element[0], element[1], element[2]); } else { return new Vector2(element[0], element[1]); } } else { return element; } } static cloneOfMathObjects(element) { if(element instanceof Matrix44$1) { return element.clone(); } else if (element instanceof Matrix33) { return element.clone(); } else if (element instanceof Vector4$1) { return element.clone(); } else if (element instanceof Vector3) { return element.clone(); } else if (element instanceof Vector2) { return element.clone(); } else { return element; } } static arrayToQuaternion(element) { if (Array.isArray(element)) { if(typeof(element[3]) !== 'undefined') { return new Quaternion(element[0], element[1], element[2], element[3]); } } else { return element; } } static makeSubArray(array, componentN) { if (componentN === 4) { return [array[0], array[1], array[2], array[3]]; } else if (componentN === 3) { return [array[0], array[1], array[2]]; } else if (componentN === 2) { return [array[0], array[1]]; } else { return array[0]; } } static vectorToArray(element) { if(element instanceof Vector2) { return [element.x, element.y]; } else if (element instanceof Vector3) { return [element.x, element.y, element.z]; } else if (element instanceof Vector4$1 || element instanceof Quaternion) { return [element.x, element.y, element.z, element.w]; } else { return element; } } /** * discriminate which Vector instance * @param element any Vector instance * @return number of Vector instance */ static compomentNumberOfVector(element ) { if(element instanceof Vector2) { return 2; } else if (element instanceof Vector3) { return 3; } else if (element instanceof Vector4$1 || element instanceof Quaternion) { return 4; } else if (Array.isArray(element)) { return element.length; } else { return 0; } } // values range must be [-1, 1] static packNormalizedVec4ToVec2(x, y, z, w, criteria) { let v0 = 0.0; let v1 = 0.0; x = (x + 1)/2.0; y = (y + 1)/2.0; z = (z + 1)/2.0; w = (w + 1)/2.0; let ir = Math.floor(x*(criteria-1.0)); let ig = Math.floor(y*(criteria-1.0)); let irg = ir*criteria + ig; v0 = irg / criteria; let ib = Math.floor(z*(criteria-1.0)); let ia = Math.floor(w*(criteria-1.0)); let iba = ib*criteria + ia; v1 =iba / criteria; return [v0, v1]; } static unProject(windowPosVec3, inversePVMat44, viewportVec4, zNear, zFar) { const input = new Vector4$1( (windowPosVec3.x - viewportVec4.x) / viewportVec4.z * 2 - 1.0, (windowPosVec3.y - viewportVec4.y) / viewportVec4.w * 2 - 1.0, // (windowPosVec3.z - zNear) / (zFar - zNear), 2 * windowPosVec3.z - 1.0, 1.0 ); const PVMat44 = inversePVMat44;//Matrix44.transpose(inversePVMat44); const out = PVMat44.multiplyVector(input); // const a = input.x * PVMat44.m03 + input.y * PVMat44.m13 + input.z * PVMat44.m23 + PVMat44.m33; // const a = input.x * PVMat44.m30 + input.y * PVMat44.m31 + input.z * PVMat44.m32 + PVMat44.m33; if (out.w === 0) { console.warn("Zero division!"); } const output = new Vector3(out.multiply(1/out.w)); return output; } } GLBoost$1["MathClassUtil"] = MathClassUtil; class AnimationUtil { constructor() { } static lerp(start, end, ratio, componentN) { if (componentN === 1) { return start * (1 - ratio) + end * ratio; } else { if (start instanceof Quaternion) { return Quaternion.qlerp(start, end, ratio); } else { return start.multiply((1 - ratio)).add(end.multiply(ratio)); } } } static interpolate(inputArray, outputArray, input, componentN, method = GLBoost$1.INTERPOLATION_LINEAR) { if (input < inputArray[0]) { return outputArray[0].clone(); // out of range! } if (inputArray[inputArray.length-1] <= input) { return outputArray[outputArray.length-1].clone(); // out of range! } if (method === GLBoost$1.INTERPOLATION_LINEAR) { for (let i = 0; i latestInputValue) { latestInputValue = inputLatestValueAtThisAttribute; } } return latestInputValue; } /** * Set animation input value (for instance frame value), This value affect all child elements in this scene graph (recursively). * @param inputName inputName name of input value. * @param inputValue input value of animation. */ setCurrentAnimationValue(inputName , inputValue ) { if ((this )._setDirtyToAnimatedElement != null) { (this )._setDirtyToAnimatedElement(inputName); } this._currentAnimationInputValues[inputName] = inputValue; } removeCurrentAnimationValue(inputName ) { delete this._currentAnimationInputValues[inputName]; } setActiveAnimationLine(lineName ) { this._activeAnimationLineName = lineName; } set translate(vec ) { this._translate = vec.clone(); this._is_translate_updated = true; this._is_trs_matrix_updated = false; this._is_inverse_trs_matrix_updated = false; this.__updateTransform(); } getTranslateNotAnimated() { if (this._is_translate_updated) { return this._translate.clone(); } else if (this._is_trs_matrix_updated) { this._translate.x = this._matrix.m03; this._translate.y = this._matrix.m13; this._translate.z = this._matrix.m23; this._is_translate_updated = true; } return this._translate.clone(); } get translate() { return this.getTranslateAtOrStatic(this._activeAnimationLineName, this._getCurrentAnimationInputValue(this._activeAnimationLineName)); } getTranslateAt(lineName , inputValue ) { let value = this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'translate'); if (value !== null) { this._translate = value; this._is_translate_updated = true; } return value; } getTranslateAtOrStatic(lineName , inputValue ) { let value = this.getTranslateAt(lineName, inputValue); if (value === null) { return this.getTranslateNotAnimated(); } return value; } set rotate(vec ) { this._rotate = vec.clone(); this._is_euler_angles_updated = true; this._is_quaternion_updated = false; this._is_trs_matrix_updated = false; this._is_inverse_trs_matrix_updated = false; this.__updateTransform(); } get rotate() { return this.getRotateAtOrStatic(this._activeAnimationLineName, this._getCurrentAnimationInputValue(this._activeAnimationLineName)); } getRotateAt(lineName , inputValue ) { let value = this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'rotate'); if (value !== null) { this._rotate = value; this._is_euler_angles_updated = true; } return value; } getRotateAtOrStatic(lineName , inputValue ) { let value = null; if (lineName != null && inputValue != null) { value = this.getRotateAt(lineName, inputValue); } if (value === null) { return this.getRotateNotAnimated(); } return value; } getRotateNotAnimated() { if (this._is_euler_angles_updated) { return this._rotate.clone(); } else if (this._is_trs_matrix_updated) { this._rotate = this._matrix.toEulerAngles(); } else if (this._is_quaternion_updated) { this._rotate = (new Matrix44$1(this._quaternion)).toEulerAngles(); } this._is_euler_angles_updated = true; return this._rotate.clone(); } set scale(vec ) { this._scale = vec.clone(); this._is_scale_updated = true; this._is_trs_matrix_updated = false; this._is_inverse_trs_matrix_updated = false; this.__updateTransform(); } get scale() { return this.getScaleAtOrStatic(this._activeAnimationLineName, this._getCurrentAnimationInputValue(this._activeAnimationLineName)); } getScaleAt(lineName , inputValue ) { let value = this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'scale'); if (value !== null) { this._scale = value.clone(); this._is_scale_updated = true; } return value; } getScaleAtOrStatic(lineName , inputValue ) { let value = null; if (lineName != null && inputValue != null) { value = this.getScaleAt(lineName, inputValue); } if (value === null) { return this.getScaleNotAnimated(); } return value; } getScaleNotAnimated() { if (this._is_scale_updated) { return this._scale.clone(); } else if (this._is_trs_matrix_updated) { let m = this._matrix; this._scale = m.getScale(); this._is_scale_updated = true; } return this._scale.clone(); } set matrix(mat ) { this._matrix = mat.clone(); this._is_trs_matrix_updated = true; this._is_translate_updated = false; this._is_euler_angles_updated = false; this._is_quaternion_updated = false; this._is_scale_updated = false; this._is_inverse_trs_matrix_updated = false; this.__updateTransform(); } get matrix() { let input = void 0; if (this._activeAnimationLineName != null) { input = this._getCurrentAnimationInputValue(this._activeAnimationLineName); } let value = this.getMatrixAtOrStatic(this._activeAnimationLineName, input); return value; } getMatrixAt(lineName , inputValue ) { let value = this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'matrix'); if (value !== null) { this._translate = value; this._is_translate_updated = true; } return value; } getMatrixNotAnimated() { if (this._is_trs_matrix_updated) { return this._matrix.clone(); } const rotationMatrix = new Matrix44$1(this.getQuaternionNotAnimated()); let scale = this.getScaleNotAnimated(); this._matrix = Matrix44$1.multiply(rotationMatrix, Matrix44$1.scale(scale)); let translateVec = this.getTranslateNotAnimated(); this._matrix.m03 = translateVec.x; this._matrix.m13 = translateVec.y; this._matrix.m23 = translateVec.z; this._is_trs_matrix_updated = true; return this._matrix.clone(); } get transformMatrix() { let input = void 0; if (this._activeAnimationLineName !== null) { input = this._getCurrentAnimationInputValue(this._activeAnimationLineName); } const matrix = this.getMatrixAtOrStatic(this._activeAnimationLineName, input); return matrix; } isTrsMatrixNeeded(lineName , inputValue ) { //console.log(this._animationLine['time']); let result = ( this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'translate') === null && this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'rotate') === null && this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'quaternion') === null && this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'scale') === null ); return result; } getMatrixAtOrStatic(lineName , inputValue ) { let input = inputValue; //console.log(this.userFlavorName + ": " + this.isTrsMatrixNeeded(lineName, inputValue)); if (this.isTrsMatrixNeeded(lineName, inputValue) && this._is_trs_matrix_updated) { return this.getMatrixNotAnimated(); } else { let quaternion = this.getQuaternionAtOrStatic(lineName, input); const rotationMatrix = new Matrix44$1(quaternion); let scale = this.getScaleAtOrStatic(lineName, input); this._matrix = Matrix44$1.multiply(rotationMatrix, Matrix44$1.scale(scale)); let translateVec = this.getTranslateAtOrStatic(lineName, input); this._matrix.m03 = translateVec.x; this._matrix.m13 = translateVec.y; this._matrix.m23 = translateVec.z; this._is_trs_matrix_updated = true; return this._matrix.clone(); } } set quaternion(quat ) { this._quaternion = quat.clone(); this._is_quaternion_updated = true; this._is_euler_angles_updated = false; this._is_trs_matrix_updated = false; this._is_inverse_trs_matrix_updated = false; this.__updateTransform(); } get quaternion() { return this.getQuaternionAtOrStatic(this._activeAnimationLineName, this._getCurrentAnimationInputValue(this._activeAnimationLineName)); } getQuaternionAt(lineName , inputValue ) { let value = this._getAnimatedTransformValue(inputValue, this._animationLine[lineName], 'quaternion'); if (value !== null) { this._quaternion = value; this._is_quaternion_updated = true; } return value; } getQuaternionAtOrStatic(lineName , inputValue ) { let value = this.getQuaternionAt(lineName, inputValue); if (value === null) { return this.getQuaternionNotAnimated(); } return value; } getQuaternionNotAnimated() { let value = null; if (this._is_quaternion_updated) { return this._quaternion.clone(); } else if (!this._is_quaternion_updated) { if (this._is_trs_matrix_updated) { value = Quaternion.fromMatrix(this._matrix); } else if (this._is_euler_angles_updated) { value = Quaternion.fromMatrix(Matrix44$1.rotateXYZ(this._rotate.x, this._rotate.y, this._rotate.z)); } else { console.log('Not Quaternion Updated in error!'); } this._quaternion = value; this._is_quaternion_updated = true; } return this._quaternion.clone(); } get inverseTransformMatrix() { if (!this._is_inverse_trs_matrix_updated) { this._invMatrix = this.transformMatrix.invert(); this._is_inverse_trs_matrix_updated = true; } return this._invMatrix.clone(); } get normalMatrix() { return new Matrix33(Matrix44$1.invert(this.transformMatrix).transpose()); } __updateTransform() { this.__updateRotation(); this.__updateTranslate(); this.__updateScale(); this.__updateMatrix(); this._needUpdate(); } __updateRotation() { if (this._is_euler_angles_updated && !this._is_quaternion_updated) { this._quaternion = Quaternion.fromMatrix(Matrix44$1.rotateXYZ(this._rotate.x, this._rotate.y, this._rotate.z)); this._is_quaternion_updated = true; } else if (!this._is_euler_angles_updated && this._is_quaternion_updated) { this._rotate = (new Matrix44$1(this._quaternion)).toEulerAngles(); this._is_euler_angles_updated = true; } else if (!this._is_euler_angles_updated && !this._is_quaternion_updated && this._is_trs_matrix_updated) { const m = this._matrix; this._quaternion = Quaternion.fromMatrix(m); this._is_quaternion_updated = true; this._rotate = m.toEulerAngles(); this._is_euler_angles_updated = true; } } __updateTranslate() { if (!this._is_translate_updated && this._is_trs_matrix_updated) { const m = this._matrix; this._translate.x = m.m03; this._translate.y = m.m13; this._translate.z = m.m23; this._is_translate_updated = true; } } __updateScale() { if (!this._is_scale_updated && this._is_trs_matrix_updated) { const m = this._matrix; this._scale.x = Math.sqrt(m.m00*m.m00 + m.m01*m.m01 + m.m02*m.m02); this._scale.y = Math.sqrt(m.m10*m.m10 + m.m11*m.m11 + m.m12*m.m12); this._scale.z = Math.sqrt(m.m20*m.m20 + m.m21*m.m21 + m.m22*m.m22); this._is_scale_updated = true; } } __updateMatrix() { if (!this._is_trs_matrix_updated && this._is_translate_updated && this._is_quaternion_updated && this._is_scale_updated) { const rotationMatrix = new Matrix44$1(this.getQuaternionNotAnimated()); let scale = this.getScaleNotAnimated(); this._matrix = Matrix44$1.multiply(rotationMatrix, Matrix44$1.scale(scale)); let translateVec = this.getTranslateNotAnimated(); this._matrix.m03 = translateVec.x; this._matrix.m13 = translateVec.y; this._matrix.m23 = translateVec.z; this._is_trs_matrix_updated = true; } } _copy(instance ) { super._copy(instance); instance._translate = this._translate.clone(); instance._scale = this._scale.clone(); instance._rotate = this._rotate.clone(); instance._quaternion = this._quaternion.clone(); instance._matrix = this._matrix.clone(); instance._animationLine = {}; for (let lineName in this._animationLine) { instance._animationLine[lineName] = {}; for (let attributeName in this._animationLine[lineName]) { instance._animationLine[lineName][attributeName] = {}; instance._animationLine[lineName][attributeName].input = this._animationLine[lineName][attributeName].input.concat(); let instanceOutput = []; let thisOutput = this._animationLine[lineName][attributeName].output; for (let i=0; i' this._accumulatedAncestryObjectUpdateNumber = -Math.MAX_VALUE; this._accumulatedAncestryObjectUpdateNumberWithoutMySelf = -Math.MAX_VALUE; this._accumulatedAncestryObjectUpdateNumberNormal = -Math.MAX_VALUE; this._accumulatedAncestryObjectUpdateNumberInv = -Math.MAX_VALUE; this._accumulatedAncestryObjectUpdateNumberJoint = -Math.MAX_VALUE; this._transparentByUser = false; this._opacity = 1.0; this._isAffectedByWorldMatrix = true; this._isAffectedByWorldMatrixAccumulatedAncestry = true; this._isAffectedByViewMatrix = true; this._isAffectedByProjectionMatrix = true; this._toInheritCurrentAnimationInputValue = true; this._camera = null; this._customFunction = null; this._isVisible = true; this._gizmos = []; this._masterElement = null; this._worldMatrix = new Matrix44$1(); } _accumulateMyAndParentNameWithUpdateInfo(currentElem) { if (currentElem._parent === null) { return currentElem.elementUpdateNumber; } else { return this._accumulateMyAndParentNameWithUpdateInfo(currentElem._parent) + currentElem.elementUpdateNumber; } } set toInheritCurrentAnimationInputValue(flg) { this._toInheritCurrentAnimationInputValue = flg; } get toInheritCurrentAnimationInputValue() { return this._toInheritCurrentAnimationInputValue; } _getCurrentAnimationInputValue(inputName) { let value = this._currentAnimationInputValues[inputName]; if (typeof(value) === 'number') { return value; } else if (this._toInheritCurrentAnimationInputValue && this._parent) { let val = this._parent._getCurrentAnimationInputValue(inputName); if (val === void 0) { val = null; } return val; } else { return null; } } _setDirtyToAnimatedElement(inputName) { if (this.hasAnimation(inputName)) { this._needUpdate(); } } get worldMatrixWithoutMySelf() { return this.getWorldMatrixWithoutMySelfAt(void 0); } getWorldMatrixWithoutMySelfAt(input) { let tempNumber = this._accumulateMyAndParentNameWithUpdateInfo(this); if (this._accumulatedWithoutMySelfAncestryObjectUpdateNumber !== tempNumber || this._matrixAccumulatedWithoutMySelfAncestry === void 0) { this._matrixAccumulatedWithoutMySelfAncestry = this._multiplyMyAndParentTransformMatrices(false, input); this._accumulatedWithoutMySelfAncestryObjectUpdateNumber = tempNumber; } return this._matrixAccumulatedWithoutMySelfAncestry.clone(); } get normalMatrix() { var tempNumber = this._accumulateMyAndParentNameWithUpdateInfo(this); //console.log(tempNumber); if (this._accumulatedAncestryObjectUpdateNumberNormal !== tempNumber || typeof this._normalMatrix === 'undefined') { let world_m = this._multiplyMyAndParentTransformMatrices(true, null); this._normalMatrix = new Matrix33(Matrix44$1.invert(world_m).transpose()); this._accumulatedAncestryObjectUpdateNumberNormal = tempNumber; } return this._normalMatrix.clone(); } _multiplyMyAndParentRotateMatrices(currentElem, withMySelf) { if (currentElem._parent === null) { if (withMySelf) { return currentElem.transformMatrixOnlyRotate; } else { return Matrix44$1.identity(); } } else { let currentMatrix = Matrix44$1.identity(); if (withMySelf) { currentMatrix = currentElem.transformMatrixOnlyRotate; } return Matrix44$1.multiply(this._multiplyMyAndParentRotateMatrices(currentElem._parent, true), currentMatrix); } } get inverseWorldMatrix() { return this.getInverseWorldMatrix(true, void 0) } get inverseWorldMatrixWithoutMySelf() { return this.getInverseWorldMatrix(false, void 0); } getInverseWorldMatrix(withMyself, input) { return Matrix44$1.invert(this._multiplyMyAndParentTransformMatrices(withMyself, input)); } _accumulateMyAndParentOpacity(currentElem) { if (currentElem._parent === null) { return currentElem.opacity; } else { return this._accumulateMyAndParentOpacity(currentElem._parent) * currentElem.opacity; } } get opacityAccumulatedAncestry() { return this._accumulateMyAndParentOpacity(this); } set opacity(opacity) { this._opacity = opacity; } get opacity() { return this._opacity; } get isTransparent() { return this._transparentByUser; } set isTransparent(flg) { this._transparentByUser = flg; } set dirty(flg) { if (flg) { this._needUpdate(); } } get parent() { return this._parent; } get elementUpdateNumber() { return this.classUniqueNumber + this._updateCountAsElement; } // used by library (not Application) toStringWithUpdateInfo() { // return '&' + this._instanceName + '#' + this._updateCountAsElement; // human readable return this._instanceName + this._updateCountAsElement; // faster } set camera(camera) { this._camera = camera; } get camera() { return this._camera; } set customFunction(func) { this._customFunction = func; } get customFunction() { return this._customFunction; } prepareToRender() { } _copy(instance) { super._copy(instance); instance._parent = this._parent; instance._invMatrix = this._invMatrix.clone(); instance._matrixGetMode = this._matrixGetMode; instance._is_inverse_trs_matrix_updated = this._is_inverse_trs_matrix_updated; instance._accumulatedAncestryObjectUpdateNumber = this._accumulatedAncestryObjectUpdateNumber; instance._accumulatedAncestryObjectUpdateNumberNormal = this._accumulatedAncestryObjectUpdateNumberNormal; instance._accumulatedAncestryObjectUpdateNumberInv = this._accumulatedAncestryObjectUpdateNumberInv; instance._transparentByUser = this._transparentByUser; instance.opacity = this.opacity; instance._activeAnimationLineName = this._activeAnimationLineName; instance._currentAnimationInputValues = {}; for (let inputName in this._currentAnimationInputValues) { instance._currentAnimationInputValues[inputName] = this._currentAnimationInputValues[inputName]; } instance._toInheritCurrentAnimationInputValue = this._toInheritCurrentAnimationInputValue; instance._camera = this._camera; instance._customFunction = this._customFunction; } set isVisible(flg) { this._isVisible = flg; } get isVisible() { return this._isVisible; } set isAffectedByWorldMatrix(flg) { this._isAffectedByWorldMatrix = flg; } get isAffectedByWorldMatrix() { return this._isAffectedByWorldMatrix; } set isAffectedByWorldMatrixAccumulatedAncestry(flg) { this._isAffectedByWorldMatrixAccumulatedAncestry = flg; } get isAffectedByWorldMatrixAccumulatedAncestry() { return this._isAffectedByWorldMatrixAccumulatedAncestry; } set isAffectedByViewMatrix(flg) { this._isAffectedByViewMatrix = flg; } get isAffectedByViewMatrix() { return this._isAffectedByViewMatrix; } set isAffectedByProjectionMatrix(flg) { this._isAffectedByProjectionMatrix = flg; } get isAffectedByProjectionMatrix() { return this._isAffectedByProjectionMatrix; } set gizmoScale(scale) { for (let gizmo of this._gizmos) { gizmo.scale = new Vector3(scale, scale, scale); } } get gizmoScale() { if (this._gizmos.length === 0) { return 1.0; } return this._gizmos[0].scale.x; } set isGizmoVisible(flg) { for (let gizmo of this._gizmos) { gizmo.isVisible = flg; } } get isGizmoVisible() { return this._gizmos[0].isVisible; } set masterElement(element) { this._masterElement = element; } get masterElement() { return this._masterElement; } get worldMatrix() { return this.getWorldMatrixAt(void 0); } getWorldMatrixAt(input) { let tempNumber = this._accumulateMyAndParentNameWithUpdateInfo(this); if (this._accumulatedAncestryObjectUpdateNumber !== tempNumber || this._matrixAccumulatedAncestry === void 0) { this._matrixAccumulatedAncestry = this._multiplyMyAndParentTransformMatrices(true, input); this._accumulatedAncestryObjectUpdateNumber = tempNumber; } return this._matrixAccumulatedAncestry.clone(); } _multiplyMyAndParentTransformMatrices(withMySelf, input) { if (input === void 0 && this._activeAnimationLineName !== null) { input = this._getCurrentAnimationInputValue(this._activeAnimationLineName); } let tempNumber = this._accumulateMyAndParentNameWithUpdateInfo(this); if (this.__updateInfoString_multiplyMyAndParentTransformMatrices !== tempNumber || this.__cache_input_multiplyMyAndParentTransformMatrices !== input || this.__cache_returnValue_multiplyMyAndParentTransformMatrices === void 0) { let currentMatrix = null; if (withMySelf) { currentMatrix = this.getMatrixAtOrStatic(this._activeAnimationLineName, input); } else { currentMatrix = Matrix44$1.identity(); } if (this._parent === null) { this.__cache_returnValue_multiplyMyAndParentTransformMatrices = currentMatrix; return currentMatrix; } this.__cache_returnValue_multiplyMyAndParentTransformMatrices = Matrix44$1.multiply(this._parent._multiplyMyAndParentTransformMatrices(true, input), currentMatrix); this.__updateInfoString_multiplyMyAndParentTransformMatrices = tempNumber; this.__cache_input_multiplyMyAndParentTransformMatrices = input; } return this.__cache_returnValue_multiplyMyAndParentTransformMatrices; } get gizmos() { return this._gizmos; } addGizmo(gizmo) { this._gizmos.push(gizmo); } readyForDiscard() { } } /** * This is the abstract class for all lights classes. Don't use this class directly.
*/ class M_AbstractLight extends M_Element { constructor(glBoostContext) { super(glBoostContext); if (this.constructor === M_AbstractLight) { throw new TypeError('Cannot construct AbstractLight instances directly.'); } this._gl = this._glContext.gl; this._isCastingShadow = true; this._isLightType = ''; this._camera = null; } prepareToRender() { if (this._camera) { if (this._camera.customFunction) { this._camera.customFunction(this); } } } set isCastingShadow(flg) { this._isCastingShadow = flg; } get isCastingShadow() { return this._isCastingShadow; } get lightType() { return this._isLightType; } isTypeAmbient() { return this._isLightType === 'ambient'; } isTypeDirectional() { return this._isLightType === 'directional'; } isTypePoint() { return this._isLightType === 'point'; } isTypeSpot() { return this._isLightType === 'spot'; } set camera(camera) { this._camera = camera; } get camera() { return this._camera; } } GLBoost$1['M_AbstractLight'] = M_AbstractLight; /** * This is a Point Light class. */ class M_PointLight extends M_AbstractLight { /** * The constructor of PointLight class. * @param {Vector4} intensity intensity as Vector4 Color * @param {HTMLCanvas|string} canvas canvas or canvas' id string. */ constructor(glBoostContext, intensity) { super(glBoostContext); this._intensity = intensity; this._isLightType = 'point'; } set intensity(vec) { this._intensity = vec; } get intensity() { return this._intensity; } } class Hash { constructor() { } static toCRC32(str) { var crc = 0, x=0, y=0; var table = Hash._crc32table; crc = crc ^ (-1); for (var i=0, iTop=str.length; i>> 8) ^ x; } return (crc ^ (-1)) >>> 0; } } Hash._crc32table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D".split(' '); class Shader extends GLBoostObject { constructor(glBoostContext) { super(glBoostContext); this._glslProgram = null; this._dirty = true; } static initMixinMethodArray() { this.prototype._classNamesOfVSDefine = this.prototype._classNamesOfVSDefine ? this.prototype._classNamesOfVSDefine : []; this.prototype._classNamesOfVSMethodDefine = this.prototype._classNamesOfVSMethodDefine ? this.prototype._classNamesOfVSMethodDefine : []; this.prototype._classNamesOfVSPreProcess = this.prototype._classNamesOfVSPreProcess ? this.prototype._classNamesOfVSPreProcess : []; this.prototype._classNamesOfVSTransform = this.prototype._classNamesOfVSTransform ? this.prototype._classNamesOfVSTransform : []; this.prototype._classNamesOfFSDefine = this.prototype._classNamesOfFSDefine ? this.prototype._classNamesOfFSDefine : []; this.prototype._classNamesOfFSMethodDefine = this.prototype._classNamesOfFSMethodDefine ? this.prototype._classNamesOfFSMethodDefine : []; this.prototype._classNamesOfFSShade = this.prototype._classNamesOfFSShade ? this.prototype._classNamesOfFSShade : []; this.prototype._classNamesOfFSPostEffect = this.prototype._classNamesOfFSPostEffect ? this.prototype._classNamesOfFSPostEffect : []; this.prototype._classNamesOfFSFinalize = this.prototype._classNamesOfFSFinalize ? this.prototype._classNamesOfFSFinalize : []; this.prototype._classNamesOfPrepare = this.prototype._classNamesOfPrepare ? this.prototype._classNamesOfPrepare : []; } static mixin(source) { // create mixin method Array this.initMixinMethodArray(); // register mixin methods to Array if(this.prototype._classNamesOfVSDefine.indexOf(source.name) === -1){ this.prototype._classNamesOfVSDefine.push(source.name); } if(this.prototype._classNamesOfVSMethodDefine.indexOf(source.name) === -1){ this.prototype._classNamesOfVSMethodDefine.push(source.name); } if(this.prototype._classNamesOfVSPreProcess.indexOf(source.name) === -1){ this.prototype._classNamesOfVSPreProcess.push(source.name); } if(this.prototype._classNamesOfVSTransform.indexOf(source.name) === -1){ this.prototype._classNamesOfVSTransform.push(source.name); } if(this.prototype._classNamesOfFSDefine.indexOf(source.name) === -1){ this.prototype._classNamesOfFSDefine.push(source.name); } if(this.prototype._classNamesOfFSMethodDefine.indexOf(source.name) === -1){ this.prototype._classNamesOfFSMethodDefine.push(source.name); } if(this.prototype._classNamesOfFSShade.indexOf(source.name) === -1){ this.prototype._classNamesOfFSShade.push(source.name); } if(this.prototype._classNamesOfFSPostEffect.indexOf(source.name) === -1){ this.prototype._classNamesOfFSPostEffect.push(source.name); } if(this.prototype._classNamesOfFSFinalize.indexOf(source.name) === -1){ this.prototype._classNamesOfFSFinalize.push(source.name); } if(this.prototype._classNamesOfPrepare.indexOf(source.name) === -1){ this.prototype._classNamesOfPrepare.push(source.name); } // mixin var target = this.prototype; source = source.prototype; Object.getOwnPropertyNames(source).forEach(function (name) { if (name !== 'constructor') Object.defineProperty(target, name, Object.getOwnPropertyDescriptor(source, name)); }); } static swapMixin(current, newone) { // register mixin methods to Array let matchIdx = this.prototype._classNamesOfVSDefine.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSDefine[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfVSMethodDefine.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSMethodDefine[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfVSPreProcess.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSPreProcess[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfVSTransform.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSTransform[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfFSDefine.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSDefine[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfFSMethodDefine.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSMethodDefine[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfFSShade.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSShade[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfFSPostEffect.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSPostEffect[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfFSFinalize.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSFinalize[matchIdx] = newone.name; } matchIdx = this.prototype._classNamesOfPrepare.indexOf(current.name); if(matchIdx !== -1){ this.prototype._classNamesOfPrepare[matchIdx] = newone.name; } // mixin var target = this.prototype; newone = newone.prototype; Object.getOwnPropertyNames(newone).forEach(function (name) { if (name !== 'constructor') Object.defineProperty(target, name, Object.getOwnPropertyDescriptor(newone, name)); }); } static removeMixin(source) { let matchIdx = this.prototype._classNamesOfVSDefine.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSDefine.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfVSMethodDefine.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSMethodDefineVSPreProcess.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfVSPreProcess.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSPreProcess.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfVSTransform.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfVSTransform.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfFSDefine.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSDefine.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfFSMethodDefine.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSMethodDefine.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfFSShade.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSShade.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfFSPostEffect.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSPostEffect.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfFSFinalize.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfFSFinalize.splice(matchIdx, 1); } matchIdx = this.prototype._classNamesOfPrepare.indexOf(source.name); if(matchIdx !== -1){ this.prototype._classNamesOfPrepare.splice(matchIdx, 1); } } static isMixin(source) { // create mixin method Array this.initMixinMethodArray(); // register mixin methods to Array if (this.prototype._classNamesOfVSDefine.indexOf(source.name) === -1) { return false; } else { return true; } } _removeDuplicatedLine(shaderString) { var splittedShaderLines = shaderString.split('\n'); for (let i=0; i=100) { splitter = ': '; } shaderTextWithLineNumber += lineIndex + splitter + shaderTextLines[i] + '\n'; } return shaderTextWithLineNumber; } _getVertexShaderString(gl, functions, existCamera_f, lights, material, extraData) { var f = functions; var shaderText = ''; var in_ = Shader._in_onVert(gl); var out_ = Shader._out_onVert(gl); shaderText = Shader._glslVer(gl); shaderText += 'precision highp float;\n'; shaderText += `${in_} vec3 aVertex_position;\n`; if (Shader._exist(f, GLBoost$1.NORMAL)) { shaderText += `attribute vec3 aVertex_normal;\n`; if (Shader._exist(f, GLBoost$1.TANGENT)) { shaderText += `attribute vec3 aVertex_tangent;\n`; } } /// define variables // start defining variables. first, sub class Shader, ... // seconds, define variables as mixin shaders let vsDefineShaderText = ''; this._classNamesOfVSDefine.forEach((className)=> { var method = this['VSDefine_' + className]; if (method) { vsDefineShaderText += '// VSDefine_' + className + ' //\n'; vsDefineShaderText += method.bind(this, in_, out_, f, lights, material, extraData)(); } }); shaderText += this._removeDuplicatedLine(vsDefineShaderText); /// define methods // start defining methods. first, sub class Shader, ... // seconds, define methods as mixin Shaders this._classNamesOfVSMethodDefine.forEach((className)=> { var method = this['VSMethodDefine_' + className]; if (method) { shaderText += '// VSMethodDefine_' + className + ' //\n'; shaderText += method.bind(this, existCamera_f, f, lights, material, extraData)(); } }); // begin of main function shaderText += 'void main(void) {\n'; shaderText += 'vec4 position_local = vec4(aVertex_position, 1.0);\n'; if (Shader._exist(f, GLBoost$1.NORMAL)) { shaderText += 'vec3 normal_local = aVertex_normal;\n'; if (Shader._exist(f, GLBoost$1.TANGENT)) { shaderText += 'vec3 tangent_local = aVertex_tangent;\n'; } } shaderText += 'bool isSkinning = false;\n'; /// PreProcess // start pre-processing. first, sub class Shader, ... // seconds, pre-process as mixin Shaders this._classNamesOfVSPreProcess.forEach((className)=> { var method = this['VSPreProcess_' + className]; if (method) { shaderText += '// VSPreProcess_' + className + ' //\n'; shaderText += method.bind(this, existCamera_f, f, lights, material, extraData)(); } }); /// Transform // start transforming. first, sub class Shader, ... // seconds, transform as mixin Shaders this._classNamesOfVSTransform.forEach((className)=> { var method = this['VSTransform_' + className]; if (method) { shaderText += '// VSTransform_' + className + ' //\n'; shaderText += method.bind(this, existCamera_f, f, lights, material, extraData)(); } }); // end of main function shaderText += '}'; return shaderText; } _getFragmentShaderString(gl, functions, lights, material, extraData) { var f = functions; var shaderText = ''; var in_ = Shader._in_onFrag(gl); shaderText += Shader._glslVer(gl); var maxDrawBuffers = this._getMaxDrawBuffers(); if (maxDrawBuffers > 1) { shaderText += Shader._glsl1DrawBufferExt(gl); } shaderText += Shader._glsl1StdDerivativeExt(gl); shaderText += Shader._glsl1ShaderTextureLodExt(gl); shaderText += 'precision highp float;\n'; for (let i=0; i { var method = this['FSDefine_' + className]; if (method) { fsDefineShaderText += '// FSDefine_' + className + ' //\n'; fsDefineShaderText += method.bind(this, in_, f, lights, material, extraData)(); } }); shaderText += this._removeDuplicatedLine(fsDefineShaderText); /// define methods // start defining methods. first, sub class Shader, ... // seconds, define methods as mixin Shaders this._classNamesOfFSMethodDefine.forEach((className)=> { var method = this['FSMethodDefine_' + className]; if (method) { shaderText += '// FSMethodDefine_' + className + ' //\n'; shaderText += method.bind(this, f, lights, material, extraData)(); } }); // begin of main function shaderText += 'void main(void) {\n'; /// Shading // start shading. first, sub class Shaders, ... // second, shade as mixin Shaders this._classNamesOfFSShade.forEach((className)=> { var method = this['FSShade_' + className]; if (method) { shaderText += '// FSShade_' + className + ' //\n'; shaderText += method.bind(this, f, gl, lights, material, extraData)(); } }); /// PostEffect // start posteffect. first, sub class Shaders, ... // second, shade as mixin Shaders this._classNamesOfFSPostEffect.forEach((className)=> { let method = this['FSPostEffect_' + className]; if (method) { shaderText += '// FSPostEffect_' + className + ' //\n'; shaderText += method.bind(this, f, gl, lights, material, extraData)(); } }); /// Finalize // start finalize. first, sub class Shaders, ... // second, shade as mixin Shaders this._classNamesOfFSFinalize.forEach((className)=> { let method = this['FSFinalize_' + className]; if (method) { shaderText += '// FSFinalize_' + className + ' //\n'; shaderText += method.bind(this, f, gl, lights, material, extraData)(); } }); // end of main function if (maxDrawBuffers > 1) { for (let i=0; i { var method = this['prepare_' + className]; if (method) { var verAttirbs = method.bind(this, gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData, canvas)(); temp = temp.concat(verAttirbs); } }); let set = new Set(temp); let vertexAttribsAsResult = []; for (let elem of set) { vertexAttribsAsResult.push(elem); } return vertexAttribsAsResult; } get dirty() { return this._dirty; } set dirty(flg) { this._dirty = flg; } setUniforms(gl, glslProgram, scene, material, camera, mesh, lights) { //super.setUniforms(gl, glslProgram, scene, material, camera, mesh, lights); } setUniformsAsTearDown(gl, glslProgram, scene, material, camera, mesh, lights) { //super.setUniformsAsTearDown(gl, glslProgram, scene, material, camera, mesh, lights); } _getShader(gl, theSource, type) { var shader; if (type == 'x-shader/x-fragment') { shader = this._glContext.createShader(this, gl.FRAGMENT_SHADER); } else if (type == 'x-shader/x-vertex') { shader = this._glContext.createShader(this, gl.VERTEX_SHADER); } else { // Unknown shader type shader = null; } gl.shaderSource(shader, theSource); // Compile the shader program gl.compileShader(shader); // See if it compiled successfully if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); console.error(gl.getShaderInfoLog(shader)); shader = null; } return shader; } _initShaders(gl, vertexShaderStr, fragmentShaderStr) { let vertexShaderStrWithLineNumber = this._addLineNumber(vertexShaderStr); let fragmentShaderStrWithLineNumber = this._addLineNumber(fragmentShaderStr); MiscUtil.consoleLog(GLBoost$1.LOG_SHADER_CODE, 'Vertex Shader:'); MiscUtil.consoleLog(GLBoost$1.LOG_SHADER_CODE, vertexShaderStrWithLineNumber); MiscUtil.consoleLog(GLBoost$1.LOG_SHADER_CODE, 'Fragment Shader:'); MiscUtil.consoleLog(GLBoost$1.LOG_SHADER_CODE, fragmentShaderStrWithLineNumber); var vertexShader = this._getShader(gl, vertexShaderStr, 'x-shader/x-vertex'); var fragmentShader = this._getShader(gl, fragmentShaderStr, 'x-shader/x-fragment'); if (vertexShader === null || fragmentShader === null) { return null; } // Create the shader program var shaderProgram = this._glContext.createProgram(this); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); this._glContext.deleteShader(this, vertexShader); this._glContext.deleteShader(this, fragmentShader); // If creating the shader program failed, alert if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); console.error(gl.getProgramInfoLog(shaderProgram)); } this._glContext.useProgram(shaderProgram); shaderProgram.vertexShaderSource = vertexShaderStrWithLineNumber; shaderProgram.fragmentShaderSource = fragmentShaderStrWithLineNumber; return shaderProgram; } getShaderProgram(expression, vertexAttribs, existCamera_f, lights_, material, extraData = {}) { var gl = this._glContext.gl; var canvasId = this._glContext.belongingCanvasId; let programToReturn = null; let lights = null; do { lights = this.getDefaultPointLightIfNotExist(lights_); lights = lights.filter((light)=>{return !light.isTypeAmbient();}); var vertexShaderText = this._getVertexShaderString(gl, vertexAttribs, existCamera_f, lights, material, extraData); var fragmentShaderText = this._getFragmentShaderString(gl, vertexAttribs, lights, material, extraData); // lookup shaderHashTable var baseText = vertexShaderText + '\n###SPLIT###\n' + fragmentShaderText; var hash = Hash.toCRC32(baseText); if (!Shader._shaderHashTable[canvasId]) { Shader._shaderHashTable[canvasId] = {}; } var hashTable = Shader._shaderHashTable[canvasId]; if (hash in hashTable) { if (hashTable[hash].code === baseText) { programToReturn = hashTable[hash].program; } else { for (let i=0; i 0) { indexStr = hash + '_' + hashTable[hash].collisionN; } else { indexStr = hash; } MiscUtil.consoleLog(GLBoost$1.LOG_SHADER_CODE, 'ShaderInstance: ' + material.shaderInstance + ' ShaderHashId: ' + indexStr); programToReturn = this._initShaders(gl, vertexShaderText, fragmentShaderText); if (programToReturn !== null) { programToReturn.createdAt = performance.now(); programToReturn.hashId = indexStr; programToReturn.glslProgramsSelfUsageCount = -1; hashTable[indexStr] = {code:baseText, program:programToReturn, collisionN:0}; Shader._shaderHashTable[canvasId] = hashTable; } else if (this.className === "SkeletalShader") { GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL++; console.log('GLBoost.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL was changed to : '+GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL); } } } while (programToReturn === null && this.className === "SkeletalShader" && GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL < 3); this._glslProgram = programToReturn; material._semanticsDic = {_glslProgram:programToReturn}; material.uniformTextureSamplerDic = {}; programToReturn._material = material; programToReturn.optimizedVertexAttribs = this._prepareAssetsForShaders(gl, programToReturn, expression, vertexAttribs, existCamera_f, lights, material, extraData); return programToReturn; } getDefaultPointLightIfNotExist(lights) { if (lights.length === 0) { if (Shader._defaultLight === null) { Shader._defaultLight = this._glBoostSystem._glBoostContext.createPointLight(GLBoost$1.VALUE_DEFAULT_POINTLIGHT_INTENSITY); } return [Shader._defaultLight]; } else { return lights; } } static _exist(functions, glboostConstantForAttributeType) { let attribute = GLBoost$1.getValueOfGLBoostConstant(glboostConstantForAttributeType); return functions.indexOf(attribute) >= 0; } _getMaxDrawBuffers() { var gl = this._glContext.gl; var isWebGL2 = Shader.isThisGLVersion_2(gl); if (isWebGL2) { return gl.getParameter(gl.MAX_DRAW_BUFFERS); } var glem = GLExtensionsManager.getInstance(this._glContext); if (glem.extDBs) { return gl.getParameter(glem.extDBs.MAX_DRAW_BUFFERS_WEBGL); } else { return 1; } } static isThisGLVersion_2(gl) { if (typeof WebGL2RenderingContext === 'undefined') { return false; } return gl instanceof WebGL2RenderingContext; } static _glslVer(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? '#version 300 es\n' : ''; } static _glsl1DrawBufferExt(gl) { return !GLBoost$1.isThisGLVersion_2(gl) ? '#extension GL_EXT_draw_buffers : require\n' : ''; } static _glsl1StdDerivativeExt(gl) { return !GLBoost$1.isThisGLVersion_2(gl) ? '#extension GL_OES_standard_derivatives : require\n' : ''; } static _glsl1ShaderTextureLodExt(gl) { return (!GLBoost$1.isThisGLVersion_2(gl) && gl.getExtension("EXT_shader_texture_lod"))? '#extension GL_EXT_shader_texture_lod : require\n' : ''; } static _in_onVert(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? 'in' : 'attribute'; } static _out_onVert(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? 'out' : 'varying'; } static _in_onFrag(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? 'in' : 'varying'; } static _texture_func(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? 'texture' : 'texture2D'; } static _textureProj_func(gl) { return GLBoost$1.isThisGLVersion_2(gl) ? 'shadowProj' : 'texture2DProj'; } static _generateLightStr(i) { let shaderText = ''; shaderText += ` vec3 lightDirection = lightDirection_world[${i}];\n`; shaderText += ` if (0.4 < lightSpotInfo[${i}].x) {\n`; // is pointlight or spotlight shaderText += ` lightDirection = normalize(lightPosition_world[${i}] - v_position_world.xyz);\n`; shaderText += ` }\n`; shaderText += ` float spotEffect = 1.0;\n`; shaderText += ` if (lightSpotInfo[${i}].x > 0.8) {\n`; // is spotlight shaderText += ` spotEffect = dot(lightDirection_world[${i}], lightDirection);\n`; shaderText += ` if (spotEffect > lightSpotInfo[${i}].y) {\n`; // lightSpotInfo[${i}].y == spotCosCutoff shaderText += ` spotEffect = pow(spotEffect, lightSpotInfo[${i}].z);\n`; // lightSpotInfo[${i}].z == spotExponent shaderText += ` } else {\n`; shaderText += ` spotEffect = 0.0;\n`; shaderText += ` }\n`; shaderText += ` }\n`; return shaderText; } static _generateShadowingStr(gl, i, isShadowEnabledAsTexture) { let shadowingText = ''; shadowingText += `float visibilityForShadow = 0.75;\n`; shadowingText += `float visibility = 1.0;\n`; shadowingText += `float visibilitySpecular = 1.0;\n`; shadowingText += `if (isShadowCasting[${i}] == 1) {// ${i}\n`; shadowingText += `vec4 shadowCoord_i = shadowCoord[${i}];\n`; shadowingText += `shadowCoord_i.z -= depthBias;\n`; if (GLBoost$1.isThisGLVersion_2(gl)) { if (isShadowEnabledAsTexture) { shadowingText += `visibilitySpecular = textureProj(uDepthTexture[${i}], shadowCoord_i);\n`; shadowingText += `visibility = visibilitySpecular + visibilityForShadow;\n`; } } else { if (isShadowEnabledAsTexture) { // shadowingText += ` shadowCoord_i.y = 1.0 - shadowCoord_i.y;\n`; shadowingText += `float depth = texture2DProj(uDepthTexture[${i}], shadowCoord_i).r;\n`; shadowingText += `if (depth < shadowCoord_i.z) {\n`; // shadowingText += `if (depth < 0.9) {\n`; shadowingText += ` visibility = visibilityForShadow;\n`; shadowingText += ` visibilitySpecular = 0.0;\n`; // shadowingText += ` visibilityLevel = 0.0;\n`; shadowingText += `}\n`; } } shadowingText += `}\n`; return shadowingText; }; static _getNormalStr(gl, material, f) { let shaderText = ''; let normalTexture = material.getTextureFromPurpose(GLBoost$1.TEXTURE_PURPOSE_NORMAL); if (!normalTexture && Shader._exist(f, GLBoost$1.NORMAL)) { shaderText += ' vec3 normal = normalize(v_normal_world);\n'; shaderText += ' vec3 normal_world = normal;\n'; } else if (material.isFlatShading || !Shader._exist(f, GLBoost$1.NORMAL)) { if (!GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL) { shaderText += ' vec3 dx = dFdx(v_position_world);\n'; shaderText += ' vec3 dy = dFdy(v_position_world);\n'; // shaderText += ' normal = dot(viewDirection_world, cross(dx, dy)) >= 0.0 ? normalize(cross(dx, dy)) : normalize(cross(dy, dx));\n'; shaderText += ' vec3 normal = normalize(cross(dx, dy));\n'; shaderText += ' vec3 normal_world = normal;\n'; } // shaderText += ' normal *= -1.0;\n'; } else if (normalTexture && Shader._exist(f, GLBoost$1.TANGENT)) { let textureFunc = Shader._texture_func(gl); shaderText += ` vec3 normal = ${textureFunc}(uNormalTexture, texcoord).xyz*2.0 - 1.0;\n`; shaderText += ` vec3 tangent_world = normalize(v_tangent_world);\n`; shaderText += ` vec3 binormal_world = normalize(v_binormal_world);\n`; shaderText += ` vec3 normal_world = normalize(v_normal_world);\n`; shaderText += ` mat3 tbnMat_tangent_to_world = mat3( tangent_world.x, tangent_world.y, tangent_world.z, binormal_world.x, binormal_world.y, binormal_world.z, normal_world.x, normal_world.y, normal_world.z );\n`; shaderText += ` normal = normalize(tbnMat_tangent_to_world * normal);\n`; shaderText += ` normal_world = normal;\n`; } return shaderText; } _multiplyAlphaToColorOfTexel(gl) { var gl = this._glContext.gl; let shaderText = ""; let textureFunc = Shader._texture_func(gl); shaderText += `vec4 multiplyAlphaToColorOfTexel(sampler2D texture, vec2 texcoord, int toMultiplyAlphaFlag) {\n`; shaderText += ` vec4 texel = ${textureFunc}(texture, texcoord);\n`; shaderText += ` if (toMultiplyAlphaFlag == 1) {\n`; shaderText += ` texel.rgb *= texel.a;\n`; shaderText += ` }\n`; shaderText += ` return texel;\n`; shaderText += `}\n`; return shaderText; } _sampler2DShadow_func() { var gl = this._glContext.gl; return GLBoost$1.isThisGLVersion_2(gl) ? 'sampler2DShadow' : 'sampler2D'; } static _set_outColor_onFrag(gl, i) { return GLBoost$1.isThisGLVersion_2(gl) ? `layout(location = ${i}) out vec4 rt${i};\n` : `vec4 rt${i};\n`; } static _set_glFragColor_inGLVer1(gl) { return !GLBoost$1.isThisGLVersion_2(gl) ? ' gl_FragColor = rt0;\n' : ''; } static _set_glFragData_inGLVer1(gl, i) { return !GLBoost$1.isThisGLVersion_2(gl) ? ` gl_FragData[${i}] = rt${i};\n` : ''; } static trySettingMatrix44ToUniform(gl, hashIdOfGLSLProgram, material, semanticsDir, semantics, matrixArray) { if (typeof semanticsDir[semantics] === 'undefined') { return; } if (typeof semanticsDir[semantics] === 'string') { gl.uniformMatrix4fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+semanticsDir[semantics]), false, matrixArray); return; } // it must be an Array... semanticsDir[semantics].forEach((uniformName)=>{ gl.uniformMatrix4fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+uniformName), false, matrixArray); }); } static trySettingMatrix33ToUniform(gl, hashIdOfGLSLProgram, material, semanticsDir, semantics, matrixArray) { if (typeof semanticsDir[semantics] === 'undefined') { return; } if (typeof semanticsDir[semantics] === 'string') { gl.uniformMatrix3fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+semanticsDir[semantics]), false, matrixArray); return; } // it must be an Array... semanticsDir[semantics].forEach((uniformName)=>{ gl.uniformMatrix3fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+uniformName), false, matrixArray); }); } static trySettingVec4ArrayToUniform(gl, hashIdOfGLSLProgram, material, semanticsDir, semantics, vecArray) { if (typeof semanticsDir[semantics] === 'undefined') { return; } if (typeof semanticsDir[semantics] === 'string') { gl.uniform4fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+semanticsDir[semantics]), vecArray); return; } // it must be an Array... semanticsDir[semantics].forEach((uniformName)=>{ gl.uniform4fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+uniformName), vecArray); }); } static trySettingVec3ArrayToUniform(gl, hashIdOfGLSLProgram, material, semanticsDir, semantics, vecArray) { if (typeof semanticsDir[semantics] === 'undefined') { return; } if (typeof semanticsDir[semantics] === 'string') { gl.uniform3fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+semanticsDir[semantics]), vecArray); return; } // it must be an Array... semanticsDir[semantics].forEach((uniformName)=>{ gl.uniform3fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+uniformName), vecArray); }); } static trySettingVec2ArrayToUniform(gl, hashIdOfGLSLProgram, material, semanticsDir, semantics, vecArray) { if (typeof semanticsDir[semantics] === 'undefined') { return; } if (typeof semanticsDir[semantics] === 'string') { gl.uniform2fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+semanticsDir[semantics]), vecArray); return; } // it must be an Array... semanticsDir[semantics].forEach((uniformName)=>{ gl.uniform2fv(material.getUniform(hashIdOfGLSLProgram, 'uniform_'+uniformName), vecArray); }); } get glslProgram() { return this._glslProgram; } readyForDiscard() { if (this._glslProgram) { this._glContext.deleteProgram(this, this._glslProgram); } super.readyForDiscard(); } getShaderParameter(material, parameterName, defaultValue) { if (typeof this[parameterName] !== 'undefined') { return this[parameterName]; } else if (typeof material.shaderParameters[parameterName] !== 'undefined') { return material.shaderParameters[parameterName]; } return defaultValue; } } Shader._instances = new Object(); Shader._shaderHashTable = {}; Shader._defaultLight = null; let singleton$3 = Symbol(); let singletonEnforcer$1 = Symbol(); class DrawKickerWorld { constructor(enforcer) { if (enforcer !== singletonEnforcer$1) { throw new Error('This is a Singleton class. get the instance using \'getInstance\' static method.'); } this._glslProgram = null; } static getInstance() { if (!this[singleton$3]) { this[singleton$3] = new DrawKickerWorld(singletonEnforcer$1); } return this[singleton$3]; } static setCamera(gl, glslProgram, material, world_m, normal_m, camera, mesh) { Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'WORLD', world_m.flatten()); Shader.trySettingMatrix33ToUniform(gl, glslProgram, material, material._semanticsDic, 'MODELVIEWINVERSETRANSPOSE', normal_m.flatten()); if (camera) { let viewMatrix; if (mesh.isAffectedByViewMatrix) { let cameraMatrix = camera.lookAtRHMatrix(); viewMatrix = cameraMatrix.multiply(camera.inverseWorldMatrixWithoutMySelf); // viewMatrix = cameraMatrix.multiply(camera.inverseWorldMatrix); } else { viewMatrix = Matrix44$1.identity(); } let projectionMatrix; if (mesh.isAffectedByProjectionMatrix) { projectionMatrix = camera.projectionRHMatrix(); } else { projectionMatrix = Matrix44$1.identity(); } Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'VIEW', viewMatrix.flatten()); Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'PROJECTION', projectionMatrix.flatten()); Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'MODELVIEW', Matrix44$1.multiply(viewMatrix, world_m).flatten()); camera._lastPVMatrixFromLight = Matrix44$1.multiply(projectionMatrix, viewMatrix); } } static setVRCamera(gl, glslProgram, material, world_m, normal_m, webvrFrameData, mesh, leftOrRight) { Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'WORLD', world_m.flatten()); Shader.trySettingMatrix33ToUniform(gl, glslProgram, material, material._semanticsDic, 'MODELVIEWINVERSETRANSPOSE', normal_m.flatten()); if (webvrFrameData) { let viewMatrix; if (mesh.isAffectedByViewMatrix) { const invertSittingToStandingTransform = (new Matrix44$1(webvrFrameData.sittingToStandingTransform, true)).invert(); const leftOrRightViewMatrix = new Matrix44$1(webvrFrameData[leftOrRight + 'ViewMatrix'], true); viewMatrix = Matrix44$1.multiply(leftOrRightViewMatrix, invertSittingToStandingTransform); } else { viewMatrix = Matrix44$1.identity(); } let projectionMatrix; if (mesh.isAffectedByProjectionMatrix) { projectionMatrix = new Matrix44$1(webvrFrameData[leftOrRight + 'ProjectionMatrix'], true); } else { projectionMatrix = Matrix44$1.identity(); } Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'VIEW', viewMatrix.flatten()); Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'PROJECTION', projectionMatrix.flatten()); Shader.trySettingMatrix44ToUniform(gl, glslProgram, material, material._semanticsDic, 'MODELVIEW', Matrix44$1.multiply(viewMatrix, world_m).flatten()); // camera._lastPVMatrixFromLight = Matrix44.multiply(projectionMatrix, viewMatrix); } } draw(data) { const gl = data.gl; const glem = data.glem; const expression = data.expression; const mesh = data.mesh; const originalMaterials = data.materials; const camera = data.camera; let lights = data.lights; const scene = data.scene; const vertices = data.vertices; const vaoDic = data.vaoDic; const vboDic = data.vboDic; const iboArrayDic = data.iboArrayDic; const geometry = data.geometry; const geometryName = data.geometryName; const primitiveType = data.primitiveType; const vertexN = data.vertexN; const renderPassIndex = data.renderPassIndex; const viewport = data.viewport; const isWebVRMode = data.isWebVRMode; const webvrFrameData = data.webvrFrameData; const forceThisMaterial = data.forceThisMaterial; var isVAOBound = glem.bindVertexArray(gl, vaoDic[geometryName]); let input = mesh._getCurrentAnimationInputValue('time'); for (let i=0; i 1) { // `OneVec4` Version [Begin] shaderText += 'uniform vec4 quatTranslationArray[' + extraData.jointN + '];\n'; shaderText += 'uniform vec3 translationScale;\n'; // `OneVec4` Version [End] } return shaderText; } VSMethodDefine_SkeletalShaderSource(f, lights, material, extraData) { let shaderText = ''; shaderText += ` mat3 toNormalMatrix(mat4 m) { float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3], a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3], a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3], a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3]; float b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32; float determinantVal = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; return mat3( a11 * b11 - a12 * b10 + a13 * b09, a12 * b08 - a10 * b11 - a13 * b07, a10 * b10 - a11 * b08 + a13 * b06, a02 * b10 - a01 * b11 - a03 * b09, a00 * b11 - a02 * b08 + a03 * b07, a01 * b08 - a00 * b10 - a03 * b06, a31 * b05 - a32 * b04 + a33 * b03, a32 * b02 - a30 * b05 - a33 * b01, a30 * b04 - a31 * b02 + a33 * b00) / determinantVal; } mat4 transposeMatrix(mat4 m) { return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]); } mat4 createMatrixFromQuaternionTransform( vec4 quaternion, vec3 translation ) { vec4 q = quaternion; vec3 t = translation; float sx = q.x * q.x; float sy = q.y * q.y; float sz = q.z * q.z; float cx = q.y * q.z; float cy = q.x * q.z; float cz = q.x * q.y; float wx = q.w * q.x; float wy = q.w * q.y; float wz = q.w * q.z; return mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz + wz), 2.0 * (cy - wy), 0.0, 2.0 * (cz - wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx + wx), 0.0, 2.0 * (cy + wy), 2.0 * (cx - wx), 1.0 - 2.0 * (sx + sy), 0.0, t.x, t.y, t.z, 1.0 ); /* return mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz + wz), 2.0 * (cy - wy), t.x, 2.0 * (cz - wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx + wx), t.y, 2.0 * (cy + wy), 2.0 * (cx - wx), 1.0 - 2.0 * (sx + sy), t.z, 0.0, 0.0, 0.0, 1.0 ); return mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), 0.0, 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), 0.0, 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy), 0.0, t.x, t.y, t.z, 1.0 ); return mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), t.x, 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), t.y, 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy), t.z, 0.0, 0.0, 0.0, 1.0 ); */ } mat4 createMatrixFromQuaternionTransformUniformScale( vec4 quaternion, vec4 translationUniformScale ) { vec4 q = quaternion; vec3 t = translationUniformScale.xyz; float scale = translationUniformScale.w; float sx = q.x * q.x; float sy = q.y * q.y; float sz = q.z * q.z; float cx = q.y * q.z; float cy = q.x * q.z; float cz = q.x * q.y; float wx = q.w * q.x; float wy = q.w * q.y; float wz = q.w * q.z; mat4 mat = mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz + wz), 2.0 * (cy - wy), 0.0, 2.0 * (cz - wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx + wx), 0.0, 2.0 * (cy + wy), 2.0 * (cx - wx), 1.0 - 2.0 * (sx + sy), 0.0, t.x, t.y, t.z, 1.0 ); /* mat4 mat = mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz + wz), 2.0 * (cy - wy), t.x, 2.0 * (cz - wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx + wx), t.y, 2.0 * (cy + wy), 2.0 * (cx - wx), 1.0 - 2.0 * (sx + sy), t.z, 0.0, 0.0, 0.0, 1.0 ); mat4 mat = mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), 0.0, 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), 0.0, 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy), 0.0, t.x, t.y, t.z, 1.0 ); mat4 mat = mat4( 1.0 - 2.0 * (sy + sz), 2.0 * (cz - wz), 2.0 * (cy + wy), t.x, 2.0 * (cz + wz), 1.0 - 2.0 * (sx + sz), 2.0 * (cx - wx), t.y, 2.0 * (cy - wy), 2.0 * (cx + wx), 1.0 - 2.0 * (sx + sy), t.z, 0.0, 0.0, 0.0, 1.0 ); */ mat4 uniformScaleMat = mat4( scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, 0.0, 1.0 ); // mat[0][0] *= scale; // mat[0][1] *= scale; // mat[0][2] *= scale; // mat[1][0] *= scale; // mat[1][1] *= scale; // mat[1][2] *= scale; // mat[2][0] *= scale; // mat[2][1] *= scale; // mat[2][2] *= scale; return mat*uniformScaleMat; } /* mat4 createMatrixFromQuaternionTransform( vec4 quaternion, vec3 translation ) { vec4 q = quaternion; vec3 t = translation; float x = q.x; float y = q.y; float z = q.z; float w = q.w; float x2 = x + x; float y2 = y + y; float z2 = z + z; float xx = x * x2; float yx = y * x2; float yy = y * y2; float zx = z * x2; float zy = z * y2; float zz = z * z2; float wx = w * x2; float wy = w * y2; float wz = w * z2; float m_0 = 1.0 - yy - zz; float m_3 = yx - wz; float m_6 = zx + wy; float m_1 = yx + wz; float m_4 = 1.0 - xx - zz; float m_7 = zy - wx; float m_2 = zx - wy; float m_5 = zy + wx; float m_8 = 1.0 - xx - yy; return mat4( m_0, m_3, m_6, 0.0, m_1, m_4, m_7, 0.0, m_2, m_5, m_8, 0.0, t.x, t.y, t.z, 0.0 ); return mat4( m_0, m_3, m_6, t.x, m_1, m_4, m_7, t.y, m_2, m_5, m_8, t.z, 0.0, 0.0, 0.0, 0.0 ); return mat4( m_0, m_1, m_2, 0.0, m_3, m_4, m_5, 0.0, m_6, m_7, m_8, 0.0, t.x, t.y, t.z, 0.0 ); return mat4( m_0, m_1, m_2, t.x, m_3, m_4, m_5, t.y, m_6, m_7, m_8, t.z, 0.0, 0.0, 0.0, 0.0 ); } */ vec4 unpackedVec2ToNormalizedVec4(vec2 vec_xy, float criteria){ float r; float g; float b; float a; float ix = floor(vec_xy.x * criteria); float v1x = ix / criteria; float v1y = ix - floor(v1x) * criteria; r = ( v1x + 1.0 ) / (criteria-1.0); g = ( v1y + 1.0 ) / (criteria-1.0); float iy = floor( vec_xy.y * criteria); float v2x = iy / criteria; float v2y = iy - floor(v2x) * criteria; b = ( v2x + 1.0 ) / (criteria-1.0); a = ( v2y + 1.0 ) / (criteria-1.0); r -= 1.0/criteria; g -= 1.0/criteria; b -= 1.0/criteria; a -= 1.0/criteria; r = r*2.0-1.0; g = g*2.0-1.0; b = b*2.0-1.0; a = a*2.0-1.0; return vec4(r, g, b, a); } `; return shaderText; } /** * */ VSPreProcess_SkeletalShaderSource(existCamera_f, f, lights, material, extraData) { let shaderText = ''; shaderText += 'vec4 weightVec = aVertex_weight;\n'; // DO NOT normalize as vec4! if (!GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL) { shaderText += 'mat4 skinMat = weightVec.x * skinTransformMatrices[int(aVertex_joint.x)];\n'; shaderText += 'skinMat += weightVec.y * skinTransformMatrices[int(aVertex_joint.y)];\n'; shaderText += 'skinMat += weightVec.z * skinTransformMatrices[int(aVertex_joint.z)];\n'; shaderText += 'skinMat += weightVec.w * skinTransformMatrices[int(aVertex_joint.w)];\n'; } else if (GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL === 1) { // `Quaterion (Vec4) Transform(Vec3)` Version shaderText += 'mat4 skinMat = weightVec.x * createMatrixFromQuaternionTransformUniformScale(quatArray[int(aVertex_joint.x)], transArray[int(aVertex_joint.x)]);\n'; shaderText += 'skinMat += weightVec.y * createMatrixFromQuaternionTransformUniformScale(quatArray[int(aVertex_joint.y)], transArray[int(aVertex_joint.y)]);\n'; shaderText += 'skinMat += weightVec.z * createMatrixFromQuaternionTransformUniformScale(quatArray[int(aVertex_joint.z)], transArray[int(aVertex_joint.z)]);\n'; shaderText += 'skinMat += weightVec.w * createMatrixFromQuaternionTransformUniformScale(quatArray[int(aVertex_joint.w)], transArray[int(aVertex_joint.w)]);\n'; } else if (GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL > 1) { // `OneVec4` Version shaderText += `vec2 criteria = vec2(4096.0, 4096.0);\n`; shaderText += `mat4 skinMat = weightVec.x * createMatrixFromQuaternionTransform( unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.x)].xy, criteria.x), unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.x)].zw, criteria.y).xyz*translationScale);\n`; shaderText += `skinMat += weightVec.y * createMatrixFromQuaternionTransform( unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.y)].xy, criteria.x), unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.y)].zw, criteria.y).xyz*translationScale);\n`; shaderText += `skinMat += weightVec.z * createMatrixFromQuaternionTransform( unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.z)].xy, criteria.x), unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.z)].zw, criteria.y).xyz*translationScale);\n`; shaderText += `skinMat += weightVec.w * createMatrixFromQuaternionTransform( unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.w)].xy, criteria.x), unpackedVec2ToNormalizedVec4(quatTranslationArray[int(aVertex_joint.w)].zw, criteria.y).xyz*translationScale);\n`; } // Calc the following... // * position_world // * normal_world // * normalMatrix // * tangent_world shaderText += 'position_world = skinMat * position_local;\n'; if (Shader._exist(f, GLBoost$1.NORMAL)) { shaderText += 'mat3 normalMatrix = toNormalMatrix(skinMat);\n'; shaderText += 'normal_world = normalize(normalMatrix * normal_local);\n'; if (Shader._exist(f, GLBoost$1.TANGENT)) { shaderText += 'tangent_world = normalize(normalMatrix * tangent_local);\n'; } } // So, you should not recompute the items in the list above. Check the isSkinning flag to avoid recalculation. shaderText += 'isSkinning = true;\n'; return shaderText; } prepare_SkeletalShaderSource(gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData) { let vertexAttribsAsResult = []; vertexAttribs.forEach((attribName)=>{ if (attribName === 'joint' || attribName === 'weight') { vertexAttribsAsResult.push(attribName); shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); } }); if (!GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL) { let skinTransformMatricesUniformLocation = this._glContext.getUniformLocation(shaderProgram, 'skinTransformMatrices'); material.setUniform(shaderProgram, 'uniform_skinTransformMatrices', skinTransformMatricesUniformLocation); material._semanticsDic['JOINTMATRIX'] = 'skinTransformMatrices'; } else if (GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL === 1) { let quatArrayUniformLocation = this._glContext.getUniformLocation(shaderProgram, 'quatArray'); material.setUniform(shaderProgram, 'uniform_quatArray', quatArrayUniformLocation); material._semanticsDic['JOINT_QUATERNION'] = 'quatArray'; let transArrayUniformLocation = this._glContext.getUniformLocation(shaderProgram, 'transArray'); material.setUniform(shaderProgram, 'uniform_transArray', transArrayUniformLocation); material._semanticsDic['JOINT_TRANSLATION'] = 'transArray'; } else if (GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL > 1) { // `OneVec4` Version [Begin] let quatArrayUniformLocation = this._glContext.getUniformLocation(shaderProgram, 'quatTranslationArray'); material.setUniform(shaderProgram, 'uniform_quatTranslationArray', quatArrayUniformLocation); material._semanticsDic['JOINT_QUATTRANSLATION'] = 'quatTranslationArray'; let transArrayUniformLocation = this._glContext.getUniformLocation(shaderProgram, 'translationScale'); material.setUniform(shaderProgram, 'uniform_translationScale', transArrayUniformLocation); // `OneVec4` Version [End] } /* // とりあえず単位行列で初期化 let identityMatrices = []; for (let i=0; i{return !light.isTypeAmbient();}).length; if(lightNumExceptAmbient > 0) { shaderText += `uniform vec4 lightDiffuse[${lightNumExceptAmbient}];\n`; shaderText += `uniform vec3 lightSpotInfo[${lightNumExceptAmbient}];\n`; shaderText += `uniform vec3 lightPosition_world[${lightNumExceptAmbient}];\n`; shaderText += `uniform vec3 lightDirection_world[${lightNumExceptAmbient}];\n`; } if (Shader._exist(f, GLBoost.NORMAL)) { shaderText += `${in_} vec3 v_normal_world;\n`; if (Shader._exist(f, GLBoost.TANGENT) && material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_NORMAL)) { shaderText += `${in_} vec3 v_tangent_world;\n`; shaderText += `${in_} vec3 v_binormal_world;\n`; } } shaderText += `${in_} vec3 v_position_world;\n`; return shaderText; } FSShade_VertexWorldShaderSource(f, gl, lights) { var shaderText = ''; return shaderText; } prepare_VertexWorldShaderSource(gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData) { var vertexAttribsAsResult = []; vertexAttribs.forEach((attribName)=>{ if (attribName === 'position' || attribName === 'normal' || attribName === 'tangent') { shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); if (shaderProgram['vertexAttribute_' + attribName] !== -1) { gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); vertexAttribsAsResult.push(attribName); } } }); material.setUniform(shaderProgram, 'uniform_objectIdsAndOutlineFlag', this._glContext.getUniformLocation(shaderProgram, 'objectIds')); material.setUniform(shaderProgram, 'uniform_worldMatrix', this._glContext.getUniformLocation(shaderProgram, 'worldMatrix')); material._semanticsDic['WORLD'] = 'worldMatrix'; material.setUniform(shaderProgram, 'uniform_normalMatrix', this._glContext.getUniformLocation(shaderProgram, 'normalMatrix')); material._semanticsDic['MODELVIEWINVERSETRANSPOSE'] = 'normalMatrix'; if (existCamera_f) { material.setUniform(shaderProgram, 'uniform_viewMatrix', this._glContext.getUniformLocation(shaderProgram, 'viewMatrix')); material._semanticsDic['VIEW'] = 'viewMatrix'; material.setUniform(shaderProgram, 'uniform_projectionMatrix', this._glContext.getUniformLocation(shaderProgram, 'projectionMatrix')); material._semanticsDic['PROJECTION'] = 'projectionMatrix'; } material.setUniform(shaderProgram, 'uniform_viewPosition', this._glContext.getUniformLocation(shaderProgram, 'viewPosition_world')); for(let i=0; i this._threshold_AABB_max || this._AABB_max.y > this._threshold_AABB_max || this._AABB_max.z > this._threshold_AABB_max)) { this._isValid_AABB_max = false; } if (this._threshold_AABB_lengthCenterToCorner != null && this._threshold_AABB_lengthCenterToCorner < this._lengthCenterToCorner) { this._isValid_AABB_lengthCenterToCorner = false; } return this; } isValid() { return this._isValid_AABB_min && this._isValid_AABB_max && this._isValid_AABB_lengthCenterToCorner; } isValid_AABB_min() { return this._isValid_AABB_min; } isValid_AABB_max() { return this._isValid_AABB_min; } isValid_AABB_lengthCenterToCorner() { return this._isValid_AABB_lengthCenterToCorner; } resetValidationFlags() { this._isValid_AABB_min = true; this._isValid_AABB_max = true; this._isValid_AABB_lengthCenterToCorner = true; } mergeAABB(aabb) { var isUpdated = false; if (aabb.isVanilla()) { return isUpdated; } if (this.isVanilla()) { this._AABB_min.x = aabb.minPoint.x; this._AABB_min.y = aabb.minPoint.y; this._AABB_min.z = aabb.minPoint.z; this._AABB_max.x = aabb.maxPoint.x; this._AABB_max.y = aabb.maxPoint.y; this._AABB_max.z = aabb.maxPoint.z; isUpdated = true; return isUpdated; } if (aabb.minPoint.x < this._AABB_min.x) { this._AABB_min.x = aabb.minPoint.x; isUpdated = true; } if (aabb.minPoint.y < this._AABB_min.y) { this._AABB_min.y = aabb.minPoint.y; isUpdated = true; } if (aabb.minPoint.z < this._AABB_min.z) { this._AABB_min.z = aabb.minPoint.z; isUpdated = true; } if (this._AABB_max.x < aabb.maxPoint.x) { this._AABB_max.x = aabb.maxPoint.x; isUpdated = true; } if (this._AABB_max.y < aabb.maxPoint.y) { this._AABB_max.y = aabb.maxPoint.y; isUpdated = true; } if (this._AABB_max.z < aabb.maxPoint.z) { this._AABB_max.z = aabb.maxPoint.z; isUpdated = true; } this.updateAllInfo(); return isUpdated; } get minPoint() { return this._AABB_min; } get maxPoint() { return this._AABB_max; } get centerPoint() { return this._centerPoint; } get lengthCenterToCorner() { return this._lengthCenterToCorner; } get sizeX() { return (this._AABB_max.x - this._AABB_min.x); } get sizeY() { return (this._AABB_max.y - this._AABB_min.y); } get sizeZ() { return (this._AABB_max.z - this._AABB_min.z); } static multiplyMatrix(matrix, aabb) { if (aabb.isVanilla()) { return aabb.clone(); } var newAabb = new AABB(); let AABB_0 = new Vector4$1(aabb._AABB_min.x, aabb._AABB_min.y, aabb._AABB_min.z, 1); let AABB_1 = new Vector4$1(aabb._AABB_max.x, aabb._AABB_min.y, aabb._AABB_min.z, 1); let AABB_2 = new Vector4$1(aabb._AABB_min.x, aabb._AABB_max.y, aabb._AABB_min.z, 1); let AABB_3 = new Vector4$1(aabb._AABB_min.x, aabb._AABB_min.y, aabb._AABB_max.z, 1); let AABB_4 = new Vector4$1(aabb._AABB_min.x, aabb._AABB_max.y, aabb._AABB_max.z, 1); let AABB_5 = new Vector4$1(aabb._AABB_max.x, aabb._AABB_min.y, aabb._AABB_max.z, 1); let AABB_6 = new Vector4$1(aabb._AABB_max.x, aabb._AABB_max.y, aabb._AABB_min.z, 1); let AABB_7 = new Vector4$1(aabb._AABB_max.x, aabb._AABB_max.y, aabb._AABB_max.z, 1); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_0))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_1))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_2))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_3))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_4))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_5))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_6))); newAabb.addPosition(new Vector3(matrix.multiplyVector(AABB_7))); newAabb.updateAllInfo(); return newAabb; } toString() { return 'AABB_min: ' + this._AABB_min + '\n' + 'AABB_max: ' + this._AABB_max + '\n' + 'centerPoint: ' + this._centerPoint + '\n' + 'lengthCenterToCorner: ' + this._lengthCenterToCorner; } } GLBoost$1['AABB'] = AABB; class FreeShader extends Shader { constructor(glBoostContext, vertexShaderText, fragmentShaderText, attributes, uniforms, textureNames) { super(glBoostContext); this._vertexShaderText = vertexShaderText; this._fragmentShaderText = fragmentShaderText; let newAttributes = {}; for (let attributeName in attributes) { switch (attributes[attributeName]) { case 'POSITION': newAttributes.position = attributeName; break; case 'NORMAL': newAttributes.normal = attributeName; break; case 'COLOR': newAttributes.color = attributeName; break; case 'TEXCOORD_0': newAttributes.texcoord = attributeName; break; case 'JOINT': newAttributes.joint = attributeName; break; case 'WEIGHT': newAttributes.weight = attributeName; break; default: newAttributes[attributes[attributeName]] = attributeName; break; } } this._attributes = newAttributes; this._uniforms = uniforms; this._textureNames = textureNames; } _getVertexShaderString(gl, functions, existCamera_f, lights, material, extraData) { return this._vertexShaderText; } _getFragmentShaderString(gl, functions, lights, material, extraData) { return this._fragmentShaderText; } _prepareAssetsForShaders(gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData) { var vertexAttribsAsResult = []; vertexAttribs.forEach((attribName)=>{ shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, this._attributes[attribName]); if (shaderProgram['vertexAttribute_' + attribName] >= 0) { gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); vertexAttribsAsResult.push(attribName); } }); let textureCount = 0; this._glContext.useProgram(shaderProgram); for (let uniformName in this._uniforms) { if (this._uniforms[uniformName] === 'TEXTURE') { //material.registerTextureUnitToUniform(material.getTexture(this._textureNames[uniformName]), shaderProgram, uniformName); /* material.uniformTextureSamplerDic[uniformName] = {}; let textureUniformLocation = this._glContext.getUniformLocation(shaderProgram, uniformName); if (textureUniformLocation < 0) { continue; } material.uniformTextureSamplerDic[uniformName].textureName = this._textureNames[uniformName]; material.uniformTextureSamplerDic[uniformName].textureUnitIndex = textureCount; this._glContext.uniform1i(textureUniformLocation, textureCount, true); */ let uTexture = material._glContext.getUniformLocation(shaderProgram, uniformName); material._glContext.uniform1i( uTexture, textureCount, true); material.setUniform(shaderProgram, uniformName, uTexture); material.uniformTextureSamplerDic[uniformName] = {}; material.uniformTextureSamplerDic[uniformName].textureUnitIndex = textureCount; material.uniformTextureSamplerDic[uniformName].textureName = this._textureNames[uniformName]; const texturePurpose = material.getTexturePurpose(this._textureNames[uniformName]); material._textureSemanticsDic[texturePurpose] = uniformName; textureCount++; } switch (this._uniforms[uniformName]) { case 'WORLD': case 'VIEW': case 'MODELVIEW': case 'MODELVIEWINVERSETRANSPOSE': case 'PROJECTION': case 'JOINTMATRIX': material.setUniform(shaderProgram, 'uniform_' + uniformName, this._glContext.getUniformLocation(shaderProgram, uniformName)); case 'TEXTURE': material.addSemanticsDic(this._uniforms[uniformName], uniformName); continue; } material.setUniform(shaderProgram, 'uniform_' + uniformName, this._glContext.getUniformLocation(shaderProgram, uniformName)); } return vertexAttribsAsResult; } get attributes() { return this._attributes; } setUniforms(gl, glslProgram, expression, material, camera, mesh, lights) { super.setUniforms(gl, glslProgram, expression, material, camera, mesh, lights); for (let uniformName in this._uniforms) { let value = this._uniforms[uniformName]; if (typeof value === 'number') { this._glContext.uniform1f(material.getUniform(glslProgram, 'uniform_' + uniformName), value, true); } else if (value instanceof Vector2) { this._glContext.uniform2f(material.getUniform(glslProgram, 'uniform_' + uniformName), value.x, value.y, true); } else if (value instanceof Vector3) { this._glContext.uniform3f(material.getUniform(glslProgram, 'uniform_' + uniformName), value.x, value.y, value.z, true); } else if (value instanceof Vector4$1) { this._glContext.uniform4f(material.getUniform(glslProgram, 'uniform_' + uniformName), value.x, value.y, value.z, value.w, true); } } for (let parameterName in material.shaderParameters) { let value = material.shaderParameters[parameterName]; if (typeof value === 'number') { this._glContext.uniform1f(material.getUniform(glslProgram, 'uniform_' + parameterName), value, true); } else if (value instanceof Vector2) { this._glContext.uniform2f(material.getUniform(glslProgram, 'uniform_' + parameterName), value.x, value.y, true); } else if (value instanceof Vector3) { this._glContext.uniform3f(material.getUniform(glslProgram, 'uniform_' + parameterName), value.x, value.y, value.z, true); } else if (value instanceof Vector4$1) { this._glContext.uniform4f(material.getUniform(glslProgram, 'uniform_' + parameterName), value.x, value.y, value.z, value.w, true); } } } } GLBoost['FreeShader'] = FreeShader; class Geometry extends GLBoostObject { constructor(glBoostContext) { super(glBoostContext); this._materials = []; this._vertexN = 0; this._vertices = null; this._indicesArray = null; this._indexStartOffsetArray = []; this._performanceHint = null; this._defaultMaterial = null; this._vertexData = []; this._extraDataForShader = {}; this._vboObj = {}; this._AABB = new AABB(); this._drawKicker = DrawKickerWorld.getInstance(); } _createShaderInstance(glBoostContext, shaderClass) { let shaderInstance = new shaderClass(glBoostContext, VertexWorldShaderSource); return shaderInstance; } /** * return all vertex attribute name list */ _allVertexAttribs(vertices) { var attribNameArray = []; for (var attribName in vertices) { if (attribName !== 'components' && attribName !== 'componentBytes' && attribName !== 'componentType') { attribNameArray.push(attribName); } } return attribNameArray; } _checkAndSetVertexComponentNumber(allVertexAttribs) { allVertexAttribs.forEach((attribName)=> { let element = this._vertices[attribName][0]; let componentN = MathClassUtil.compomentNumberOfVector(element); if (componentN === 0) { // if 0, it must be a number. so users must set components info. return; } if (typeof this._vertices.components === 'undefined') { this._vertices.components = {}; } if (typeof this._vertices.componentType === 'undefined') { this._vertices.componentType = {}; } this._vertices.components[attribName] = componentN; this._vertices.componentType[attribName] = 5126; }); } _calcBaryCentricCoord(vertexNum, positionElementNumPerVertex) { this._vertices.barycentricCoord = new Float32Array(vertexNum*positionElementNumPerVertex); this._vertices.components.barycentricCoord = 3; this._vertices.componentType.barycentricCoord = 5126; // gl.FLOAT if (!this._indicesArray) { for (let i=0; i { if (attribName === 'barycentricCoord') { return; } if (attribName === 'tangent') { return; } if (typeof this._vertices[attribName].buffer !== 'undefined') { return; } let vertexAttribArray = []; this._vertices[attribName].forEach((elem, index) => { let element = this._vertices[attribName][index]; Array.prototype.push.apply(vertexAttribArray, MathClassUtil.vectorToArray(element)); }); this._vertices[attribName] = vertexAttribArray; }); // for Tangent if (this._vertices.texcoord) { this._calcTangent(vertexNum, positionElementNumPerVertex, texcoordElementNumPerVertex, primitiveType); } // for Raycast Picking this._calcArenbergInverseMatrices(primitiveType); // Normal Array to Float32Array allVertexAttribs.forEach((attribName)=> { if (typeof this._vertices[attribName].buffer === 'undefined') { this._vertices[attribName] = new Float32Array(this._vertices[attribName]); } }); for (let i=0; i { let element = vertices[attribName][index]; Array.prototype.push.apply(vertexAttribArray, MathClassUtil.vectorToArray(element)); if (attribName === 'position' && !(skipUpdateAABB === true)) { let componentN = this._vertices.components[attribName]; this._AABB.addPositionWithArray(vertexAttribArray, index * componentN); } this._vertices[attribName] = vertexAttribArray; }); } if(!(skipUpdateAABB === true)) { this._AABB.updateAllInfo(); } for (let attribName in vertices) { if (this._vboObj[attribName]) { let float32AryVertexData = new Float32Array(this._vertices[attribName]); gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); gl.bufferSubData(gl.ARRAY_BUFFER, 0, float32AryVertexData); gl.bindBuffer(gl.ARRAY_BUFFER, null); } else { return false; } } return true; } setUpVertexAttribs(gl, glslProgram, allVertexAttribs) { var optimizedVertexAttribs = glslProgram.optimizedVertexAttribs; // setup vertex layouts allVertexAttribs.forEach((attribName)=> { if (optimizedVertexAttribs.indexOf(attribName) != -1) { gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); gl.vertexAttribPointer(glslProgram['vertexAttribute_' + attribName], this._vertices.components[attribName], this._vertices.componentType[attribName], false, 0, 0); } }); } setUpEnableVertexAttribArrays(gl, glslProgram, allVertexAttribs) { var optimizedVertexAttribs = glslProgram.optimizedVertexAttribs; allVertexAttribs.forEach((attribName)=> { if (optimizedVertexAttribs.indexOf(attribName) != -1) { gl.enableVertexAttribArray(glslProgram['vertexAttribute_' + attribName]); } }); } setUpDisableAllVertexAttribArrays(gl, glslProgram) { for (let i=0; i<8; i++) { gl.disableVertexAttribArray(i); } } setUpDisableVertexAttribArrays(gl, glslProgram, allVertexAttribs) { var optimizedVertexAttribs = glslProgram.optimizedVertexAttribs; allVertexAttribs.forEach((attribName)=> { if (optimizedVertexAttribs.indexOf(attribName) != -1) { gl.disableVertexAttribArray(glslProgram['vertexAttribute_' + attribName]); } }); } _getVAO() { return Geometry._vaoDic[this.toString()]; } _getAllVertexAttribs() { return this._allVertexAttribs(this._vertices); } prepareGLSLProgram(expression, material, existCamera_f, lights, shaderClass = void 0, argShaderInstance = void 0) { let vertices = this._vertices; let _optimizedVertexAttribs = this._allVertexAttribs(vertices, material); let shaderInstance = null; if (argShaderInstance) { shaderInstance = argShaderInstance; } else { if (shaderClass) { shaderInstance = this._createShaderInstance(this._glBoostSystem, shaderClass); } else { shaderInstance = this._createShaderInstance(this._glBoostSystem, material.shaderClass); } } shaderInstance.getShaderProgram(expression, _optimizedVertexAttribs, existCamera_f, lights, material, this._extraDataForShader); return shaderInstance; } _setVertexNtoSingleMaterial(material, index) { // if this mesh has only one material... //if (material.getVertexN(this) === 0) { if (this._indicesArray && this._indicesArray.length > 0) { material.setVertexN(this, this._indicesArray[index].length); } else { material.setVertexN(this, this._vertexN); } //} } _getAppropriateMaterials(mesh) { let materials = null; if (this._materials.length > 0) { materials = this._materials; } else if (mesh.material){ materials = [mesh.material]; } else { mesh.material = this._glBoostSystem._defaultMaterial; materials = [mesh.material]; } return materials; } getIndexStartOffsetArrayAtMaterial(i) { return this._indexStartOffsetArray[i]; } prepareToRender(expression, existCamera_f, lights, meshMaterial, mesh, shaderClass = void 0, argMaterials = void 0) { var vertices = this._vertices; var gl = this._glContext.gl; var glem = GLExtensionsManager.getInstance(this._glContext); this._vertexN = vertices.position.length / vertices.components.position; var allVertexAttribs = this._allVertexAttribs(vertices); // create VAO if (Geometry._vaoDic[this.toString()]) ; else { var vao = this._glContext.createVertexArray(this); Geometry._vaoDic[this.toString()] = vao; } glem.bindVertexArray(gl, Geometry._vaoDic[this.toString()]); let doAfter = false; allVertexAttribs.forEach((attribName)=> { // create VBO if (this._vboObj[attribName]) { gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); } else { let vbo = this._glContext.createBuffer(this); this._vboObj[attribName] = vbo; gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); // if (typeof this._vertices[attribName].buffer !== 'undefined') { gl.bufferData(gl.ARRAY_BUFFER, this._vertices[attribName], this._performanceHint); // } else { // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._vertices[attribName]), this._performanceHint); // } //gl.bindBuffer(gl.ARRAY_BUFFER, null); doAfter = true; } }); if (doAfter) { if (Geometry._iboArrayDic[this.toString()]) { gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Geometry._iboArrayDic[this.toString()] ); } else { if (this._indicesArray) { let indices = []; for (let i=0; i { let thisLength = this._vertices[attribName].length; let allGeomLength = 0; geometrys.forEach((geometry) => { allGeomLength += geometry._vertices[attribName].length; }); typedArrayDic[attribName] = new Float32Array(thisLength + allGeomLength); }); let lastThisLengthDic = {}; allVertexAttribs.forEach((attribName)=> { lastThisLengthDic[attribName] = 0; }); geometrys.forEach((geometry, index) => { let typedSubArrayDic = {}; allVertexAttribs.forEach((attribName)=> { let typedArray = typedArrayDic[attribName]; if (index === 0) { lastThisLengthDic[attribName] = geometrys[index]._vertices[attribName].length; } let end = (typeof geometrys[index+1] !== 'undefined') ? lastThisLengthDic[attribName] + geometrys[index+1]._vertices[attribName].length : void 0; typedSubArrayDic[attribName] = typedArray.subarray(0, end); lastThisLengthDic[attribName] = end; }); this.mergeInner(geometry, typedSubArrayDic, (index === 0)); }); } else { let geometry = geometrys; let typedArrayDic = {}; let allVertexAttribs = this._allVertexAttribs(this._vertices); allVertexAttribs.forEach((attribName)=> { let thisLength = this._vertices[attribName].length; let geomLength = geometry._vertices[attribName].length; typedArrayDic[attribName] = new Float32Array(thisLength + geomLength); }); this.mergeInner(geometry, typedArrayDic); } } /** * */ mergeInner(geometry, typedArrayDic, isFirst = false) { let gl = this._glContext.gl; let baseLen = this._vertices.position.length / this._vertices.components.position; if (this === geometry) { console.assert('don\'t merge same geometry!'); } let allVertexAttribs = this._allVertexAttribs(this._vertices); allVertexAttribs.forEach((attribName)=> { let thisLength = this._vertices[attribName].length; let geomLength = geometry._vertices[attribName].length; let float32array = typedArrayDic[attribName]; if (isFirst) { float32array.set(this._vertices[attribName], 0); } float32array.set(geometry._vertices[attribName], thisLength); this._vertices[attribName] = float32array; if (typeof this._vboObj[attribName] !== 'undefined') { gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); gl.bufferData(gl.ARRAY_BUFFER, this._vertices[attribName], this._performanceHint); gl.bindBuffer(gl.ARRAY_BUFFER, null); } }); let geometryIndicesN = geometry._indicesArray.length; for (let i = 0; i < geometryIndicesN; i++) { for (let j = 0; j < geometry._indicesArray[i].length; j++) { geometry._indicesArray[i][j] += baseLen; } this._indicesArray.push(geometry._indicesArray[i]); if (geometry._materials[i]) { this._materials.push(geometry._materials[i]); } } this._vertexN += geometry._vertexN; } mergeHarder(geometrys) { if (Array.isArray(geometrys)) { let typedArrayDic = {}; let allVertexAttribs = this._allVertexAttribs(this._vertices); allVertexAttribs.forEach((attribName)=> { let thisLength = this._vertices[attribName].length; let allGeomLength = 0; geometrys.forEach((geometry) => { allGeomLength += geometry._vertices[attribName].length; }); typedArrayDic[attribName] = new Float32Array(thisLength + allGeomLength); }); let lastThisLengthDic = {}; allVertexAttribs.forEach((attribName)=> { lastThisLengthDic[attribName] = 0; }); geometrys.forEach((geometry, index) => { let typedSubArrayDic = {}; allVertexAttribs.forEach((attribName)=> { let typedArray = typedArrayDic[attribName]; if (index === 0) { lastThisLengthDic[attribName] = geometrys[index]._vertices[attribName].length; } let end = (typeof geometrys[index+1] !== 'undefined') ? lastThisLengthDic[attribName] + geometrys[index+1]._vertices[attribName].length : void 0; typedSubArrayDic[attribName] = typedArray.subarray(0, end); lastThisLengthDic[attribName] = end; }); this.mergeHarderInner(geometry, typedSubArrayDic, (index === 0)); }); } else { let geometry = geometrys; let typedArrayDic = {}; let allVertexAttribs = this._allVertexAttribs(this._vertices); allVertexAttribs.forEach((attribName)=> { let thisLength = this._vertices[attribName].length; let geomLength = geometry._vertices[attribName].length; typedArrayDic[attribName] = new Float32Array(thisLength + geomLength); }); this.mergeHarderInner(geometry, typedArrayDic); } } /** * take no thought geometry's materials * */ mergeHarderInner(geometry, typedArrayDic, isFirst = false) { let gl = this._glContext.gl; let baseLen = this._vertices.position.length / this._vertices.components.position; if (this === geometry) { console.assert('don\'t merge same geometry!'); } let allVertexAttribs = this._allVertexAttribs(this._vertices); allVertexAttribs.forEach((attribName)=> { let thisLength = this._vertices[attribName].length; let geomLength = geometry._vertices[attribName].length; let float32array = typedArrayDic[attribName]; if (isFirst) { float32array.set(this._vertices[attribName], 0); } float32array.set(geometry._vertices[attribName], thisLength); this._vertices[attribName] = float32array; if (typeof this._vboObj[attribName] !== 'undefined') { gl.bindBuffer(gl.ARRAY_BUFFER, this._vboObj[attribName]); gl.bufferData(gl.ARRAY_BUFFER, this._vertices[attribName], this._performanceHint); gl.bindBuffer(gl.ARRAY_BUFFER, null); } }); for (let i = 0; i < this._indicesArray.length; i++) { let len = geometry._indicesArray[i].length; for (let j = 0; j < len; j++) { let idx = geometry._indicesArray[i][j]; this._indicesArray[i].push(baseLen + idx); } if (this._materials[i]) { this._materials[i].setVertexN(this, this._materials[i].getVertexN(geometry)); } } this._vertexN += geometry._vertexN; } set materials(materials) { this._materials = materials; } get materials() { return this._materials; } get centerPosition() { return this._AABB.centerPoint; } setExtraDataForShader(name, value) { this._extraDataForShader[name] = value; } getExtraDataForShader(name) { return this._extraDataForShader[name]; } isTransparent(mesh) { let materials = this._getAppropriateMaterials(mesh); let isTransparent = false; materials.forEach((material)=>{ if (material.isTransparent()) { isTransparent = true; } }); return isTransparent; } get AABB() { return this._AABB;//.clone(); } get rawAABB() { return this._AABB; } isIndexed() { return !!Geometry._iboArrayDic[this.toString()]; } getTriangleCount(mesh) { let gl = this._glContext.gl; let materials = this._getAppropriateMaterials(mesh); let count = 0; for (let i=0; i <--- return null; } if (faceNormal.dotProduct(dirVec3) > 0 && !isBackFacePickable) { // ---> ---> return null; } const vec3 = Vector3.subtract(origVec3, this._vertices.arenberg3rdPosition[i]); const convertedOrigVec3 = this._vertices.inverseArenbergMatrix[i].multiplyVector(vec3); const convertedDirVec3 = this._vertices.inverseArenbergMatrix[i].multiplyVector(dirVec3); if (convertedDirVec3.z >= -(1e-6) && convertedDirVec3.z <= (1e-6)) { return null; } const t = -convertedOrigVec3.z / convertedDirVec3.z; if(t <= (1e-5)) { return null; } const u = convertedOrigVec3.x + t * convertedDirVec3.x; const v = convertedOrigVec3.y + t * convertedDirVec3.y; if (u < 0.0 || v < 0.0 || (u + v) > 1.0) { return null; } const fDat = 1.0 - u - v; const pos0Vec3 = new Vector3( this._vertices.position[pos0IndexBase], this._vertices.position[pos0IndexBase + 1], this._vertices.position[pos0IndexBase + 2] ); const pos1Vec3 = new Vector3( this._vertices.position[pos1IndexBase], this._vertices.position[pos1IndexBase + 1], this._vertices.position[pos1IndexBase + 2] ); const pos2Vec3 = new Vector3( this._vertices.position[pos2IndexBase], this._vertices.position[pos2IndexBase + 1], this._vertices.position[pos2IndexBase + 2] ); const pos0 = Vector3.multiply(pos0Vec3, u); const pos1 = Vector3.multiply(pos1Vec3, v); const pos2 = Vector3.multiply(pos2Vec3, fDat); const intersectedPosVec3 = Vector3.add(Vector3.add(pos0, pos1), pos2); return [t, intersectedPosVec3]; } _calcArenbergInverseMatrices(primitiveType) { const positionElementNumPerVertex = this._vertices.components.position; let incrementNum = 3; // gl.TRIANGLES if (primitiveType === GLBoost$1.TRIANGLE_STRIP) { // gl.TRIANGLE_STRIP incrementNum = 1; } this._vertices.inverseArenbergMatrix = []; this._vertices.arenberg3rdPosition = []; this._vertices.faceNormal = []; if (!this._indicesArray) { for (let i=0; i{ if (this.BlendShapeShaderSource_isShapeTarget(attribName)) { shaderText+=`${in_} vec3 aVertex_${attribName};\n`; shaderText+='uniform float blendWeight_' + attribName + ';\n'; } }); return shaderText; } VSTransform_BlendShapeShaderSource(existCamera_f, f, lights, material, extraData) { var shaderText = ''; var numOfShapeTargets = this.BlendShapeShaderSource_numberOfShapeTargets(f); shaderText += ' vec3 blendedPosition = aVertex_position;\n'; f.forEach((attribName)=>{ if (this.BlendShapeShaderSource_isShapeTarget(attribName)) { shaderText += 'blendedPosition += (aVertex_' + attribName + ' - aVertex_position) * blendWeight_' + attribName + ';\n'; } }); if (existCamera_f) { shaderText += ' gl_Position = pvwMatrix * vec4(blendedPosition, 1.0);\n'; } else { shaderText += ' gl_Position = vec4(blendedPosition, 1.0);\n'; } return shaderText; } prepare_BlendShapeShaderSource(gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData) { var vertexAttribsAsResult = []; vertexAttribs.forEach((attribName)=>{ if (this.BlendShapeShaderSource_isShapeTarget(attribName)) { // if POSITION and ShapeTargets... vertexAttribsAsResult.push(attribName); shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); } }); vertexAttribs.forEach((attribName)=>{ if (this.BlendShapeShaderSource_isShapeTarget(attribName)) { // Specifically, this uniform location is saved directly to the material. material['uniform_FloatSampler_blendWeight_' + attribName] = this._glContext.getUniformLocation(shaderProgram, 'blendWeight_' + attribName); // Initially zero initialization this._glContext.uniform1f(material['uniform_FloatSampler_blendWeight_' + attribName], 0.0, true); } }); return vertexAttribsAsResult; } BlendShapeShaderSource_isShapeTarget(attribName) { return !Shader._exist(attribName, GLBoost.POSITION) && !Shader._exist(attribName, GLBoost.COLOR) && !Shader._exist(attribName, GLBoost.TEXCOORD); } BlendShapeShaderSource_numberOfShapeTargets(attributes) { var count = 0; attributes.forEach((attribName)=>{ if (this.BlendShapeShaderSource_isShapeTarget(attribName)) { count += 1; } }); return count; } } /* */ class BlendShapeGeometry extends Geometry { constructor(glBoostContext) { super(glBoostContext); this._blendWeight_1 = 0.0; this._blendWeight_2 = 0.0; this._blendWeight_3 = 0.0; this._blendWeight_4 = 0.0; this._blendWeight_5 = 0.0; this._blendWeight_6 = 0.0; this._blendWeight_7 = 0.0; this._blendWeight_8 = 0.0; this._blendWeight_9 = 0.0; this._blendWeight_10 = 0.0; this._currentRenderPassIndex = 0; this._materialForBlend = null; } draw(data ) { this._currentRenderPassIndex = data.renderPass_index; super.draw({ expression: data.expression, lights: data.lights, camera: data.camera, mesh: data.mesh, scene: data.scene, renderPassIndex: data.renderPassIndex, viewport: data.viewport, isWebVRMode: data.isWebVRMode, webvrFrameData: data.webvrFrameData}); } prepareToRender(expression, existCamera_f, pointLight, meshMaterial, mesh) { // before prepareForRender of 'Geometry' class, a new 'BlendShapeShader'(which extends default shader) is assigned. if (meshMaterial) { this._materialForBlend = meshMaterial; } else { this._materialForBlend = this._defaultMaterial; } class BlendShapeShader extends this._materialForBlend.shaderClass { constructor(glBoostContext, basicShader) { super(glBoostContext, basicShader); BlendShapeShader.mixin(BlendShapeShaderSource); } } this._materialForBlend.shaderClass = BlendShapeShader; super.prepareToRender(expression, existCamera_f, pointLight, meshMaterial, mesh); } _setBlendWeightToGlslProgram(blendTargetNumber , weight ) { let blendTarget = GLBoost$1.getValueOfGLBoostConstant(blendTargetNumber); let materials = [this._materialForBlend]; for (let i=0; i{return !light.isTypeAmbient();}).length; //shaderText += `uniform mat4 depthPVMatrix[${lightNumExceptAmbient}];\n`; //shaderText += `${out_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; return shaderText; } VSTransform_VertexWorldShadowShaderSource(existCamera_f, f, lights, material, extraData) { var shaderText = ''; let gl = this._glContext.gl; return shaderText; } FSDefine_VertexWorldShadowShaderSource(in_, f, lights, material, extraData) { let shaderText = ''; shaderText += 'uniform float depthBias;\n'; let lightNumExceptAmbient = lights.filter((light)=>{return !light.isTypeAmbient();}).length; // shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; if (lightNumExceptAmbient > 0) { shaderText += `uniform mat4 depthPVMatrix[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_VertexWorldShadowShaderSource(f, gl, lights) { let shaderText = ''; shaderText += 'float visibilityLevel = 1.0;\n'; if (lights.length > 0) { shaderText += ` vec4 shadowCoord[${lights.length}];\n`; } for (let i=0; i{ if (attribName === 'position' || attribName === 'normal') { shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); if (shaderProgram['vertexAttribute_' + attribName] !== -1) { gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); vertexAttribsAsResult.push(attribName); } } }); for (let i=0; i 0.5 && rt0.a < uAlphaTestParameters.y) { discard; } `; return shaderText; } prepare_DecalShaderSource(gl, shaderProgram, expression, vertexAttribs, existCamera_f, lights, material, extraData) { var vertexAttribsAsResult = []; vertexAttribs.forEach((attribName)=>{ if (attribName === 'color' || attribName === 'texcoord') { shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); if (shaderProgram['vertexAttribute_' + attribName] !== -1) { gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); vertexAttribsAsResult.push(attribName); } } }); material.setUniform(shaderProgram, 'uniform_materialBaseColor', this._glContext.getUniformLocation(shaderProgram, 'materialBaseColor')); let diffuseTexture = material.getTextureFromPurpose(GLBoost$1.TEXTURE_PURPOSE_DIFFUSE); if (!diffuseTexture) { diffuseTexture = this._glBoostSystem._glBoostContext.defaultDummyTexture; } if (diffuseTexture.toMultiplyAlphaToColorPreviously) { let uIsTextureToMultiplyAlphaToColorPreviously = this._glContext.getUniformLocation(shaderProgram, 'uIsTextureToMultiplyAlphaToColorPreviously'); material.setUniform(shaderProgram, 'uIsTextureToMultiplyAlphaToColorPreviously', uIsTextureToMultiplyAlphaToColorPreviously); } material.setUniform(shaderProgram, 'uniform_alphaTestParameters', this._glContext.getUniformLocation(shaderProgram, 'uAlphaTestParameters')); material.registerTextureUnitToUniform(GLBoost$1.TEXTURE_PURPOSE_DIFFUSE, shaderProgram, 'uTexture'); material.registerTextureUnitToUniform(GLBoost$1.TEXTURE_PURPOSE_NORMAL, shaderProgram, 'uNormalTexture'); return vertexAttribsAsResult; } } class DecalShader extends WireframeShader { constructor(glBoostContext) { super(glBoostContext); DecalShader.mixin(VertexWorldShadowShaderSource); DecalShader.mixin(DecalShaderSource); this._lut = null; } setUniforms(gl, glslProgram, scene, material, camera, mesh, lights) { super.setUniforms(gl, glslProgram, scene, material, camera, mesh, lights); let baseColor = null; if (material.className.indexOf('ClassicMaterial') !== -1) { baseColor = material.baseColor; } else { baseColor = new Vector4$1(1.0, 1.0, 1.0, 1.0); } this._glContext.uniform4f(material.getUniform(glslProgram, 'uniform_materialBaseColor'), baseColor.x, baseColor.y, baseColor.z, baseColor.w, true); let diffuseTexture = material.getTextureFromPurpose(GLBoost$1.TEXTURE_PURPOSE_DIFFUSE); if (diffuseTexture) { // material.uniformTextureSamplerDic['uTexture'].textureName = diffuseTexture.userFlavorName; material.updateTextureInfo(GLBoost$1.TEXTURE_PURPOSE_DIFFUSE, 'uTexture'); this._glContext.uniform1i(material.getUniform(glslProgram, 'uIsTextureToMultiplyAlphaToColorPreviously'), diffuseTexture.toMultiplyAlphaToColorPreviously, true); } const alphaCutoff = material.alphaCutoff; const isAlphaTestEnable = material.isAlphaTest; this._glContext.uniform2f(material.getUniform(glslProgram, 'uniform_alphaTestParameters'), isAlphaTestEnable ? 1.0 : 0.0, alphaCutoff, true); // For Shadow for (let i=0; i { if (state === 3042) { // gl.BLEND isTransparent = true; } }); } } return isTransparent; } set name(name) { this._name = name; this._updateCount(); } get name() { return this._name; } setVertexN(geom, num) { this._vertexNofGeometries[geom] = num; this._updateCount(); } getVertexN(geom) { return (typeof this._vertexNofGeometries[geom] === 'undefined') ? 0 : this._vertexNofGeometries[geom]; } /** * bind the texture. For any value, it returns true if we call WebGL's bindTexture function, false otherwise. */ setUpTexture(textureName, textureUnitIndex) { var gl = this._gl; let texture = this.getTexture(textureName); let isCalledWebGLBindTexture = true; if (texture) { isCalledWebGLBindTexture = texture.setUp(textureUnitIndex); return isCalledWebGLBindTexture; } else { this._glBoostSystem._glBoostContext.defaultDummyTexture.setUp(textureUnitIndex); // gl.bindTexture(gl.TEXTURE_2D, null); isCalledWebGLBindTexture = true; return isCalledWebGLBindTexture; } } tearDownTexture(textureName, textureUnitIndex) { let texture = this.getTexture(textureName); if (texture) { texture.tearDown(textureUnitIndex); } } _setUpMaterialStates(states) { let gl = this._gl; if (states) { if (states.enable) { states.enable.forEach((state)=>{ gl.enable(state); }); } if (states.functions) { for (let functionName in states.functions) { gl[functionName].apply(gl, states.functions[functionName]); } } } } setUpStates(mesh) { let globalStatesUsage = this._glBoostSystem._glBoostContext.globalStatesUsage; if (this._globalStatesUsage) { globalStatesUsage = this._globalStatesUsage; } switch (globalStatesUsage) { case GLBoost$1.GLOBAL_STATES_USAGE_DO_NOTHING: break; case GLBoost$1.GLOBAL_STATES_USAGE_IGNORE: this._setUpMaterialStates(this._states); break; case GLBoost$1.GLOBAL_STATES_USAGE_INCLUSIVE: this._glBoostSystem._glBoostContext.reflectGlobalGLState(); this._setUpMaterialStates(this._states); break; case GLBoost$1.GLOBAL_STATES_USAGE_EXCLUSIVE: this._glBoostSystem._glBoostContext.reflectGlobalGLState(); break; default: break; } if (mesh.isTransparent || this.isTransparent) { //this._gl.disable(2929); this._gl.enable(3042); //this._gl.colorMask(true, true, true, false); } } tearDownStates() { this._glBoostSystem._glBoostContext.disableAllGLState(); this._setUpMaterialStates({ functions : this._stateFunctionsToReset }); } setUniform(glslProgram, uniformLocationName, uniformLocation) { if (!this._shaderUniformLocationsOfExpressions[glslProgram.hashId]) { this._shaderUniformLocationsOfExpressions[glslProgram.hashId] = {}; } this._shaderUniformLocationsOfExpressions[glslProgram.hashId][uniformLocationName] = uniformLocation; glslProgram['uniform_' + uniformLocationName] = uniformLocationName; if (uniformLocation != null) { uniformLocation.uniformLocationName = uniformLocationName; } this._updateCount(); } getUniform(glslProgram, uniformLocationName) { if (typeof this._shaderUniformLocationsOfExpressions[glslProgram.hashId] !== 'undefined') { return this._shaderUniformLocationsOfExpressions[glslProgram.hashId][uniformLocationName]; } return void 0; } set isVisible(flg) { this._isVisibleForGeometiesAssginedByThisMaterial = flg; this._updateCount(); } get isVisible() { return this._isVisibleForGeometiesAssginedByThisMaterial; } set globalStatesUsage(usage) { this._globalStatesUsage = usage; this._updateCount(); } get globalStatesUsage() { return this._globalStatesUsage; } get shaderParameters() { return this._shaderParametersForShaderInstance; } set shaderParameters(shaderParameterDic) { this._shaderParametersForShaderInstance = shaderParameterDic; } addSemanticsDic(uniform, uniformName) { if (typeof this._semanticsDic[uniform] === 'undefined') { this._semanticsDic[uniform] = uniformName; } else if (typeof this._semanticsDic[uniform] === 'string') { let tmpSemanticsStr = this._semanticsDic[uniform]; this._semanticsDic[uniform] = []; this._semanticsDic[uniform].push(tmpSemanticsStr); this._semanticsDic[uniform].push(uniformName); } else { // it must be Array this._semanticsDic[uniform].push(uniformName); } } removeSemanticsDic(uniform) { delete this._semanticsDic[uniform]; } readyForDiscard() { for (let userFlavorName in this._textureDic) { this.removeTexture(userFlavorName, true); } if (this._shaderInstance) { this._shaderInstance.readyForDiscard(); } this._shaderInstance = null; } registerTextureUnitToUniform(texturePurpose, shaderProgram, uniformName) { const texture = this.getTextureFromPurpose(texturePurpose); if (texture != null) { let uTexture = this._glContext.getUniformLocation(shaderProgram, uniformName); let index = Object.keys(this._textureSemanticsDic).indexOf(''+texturePurpose); index = (index !== -1) ? index : Object.keys(this._textureSemanticsDic).length; this._glContext.uniform1i( uTexture, index, true); this.setUniform(shaderProgram, uniformName, uTexture); this.uniformTextureSamplerDic[uniformName] = {}; this.uniformTextureSamplerDic[uniformName].textureUnitIndex = index; this.uniformTextureSamplerDic[uniformName].textureName = texture.userFlavorName; this._textureSemanticsDic[texturePurpose] = uniformName; } } updateTextureInfo(texturePurpose, uniformName) { let texture = this.getTextureFromPurpose(texturePurpose); if (texture != null) { let index = Object.keys(this._textureSemanticsDic).indexOf(''+texturePurpose); index = (index !== -1) ? index : Object.keys(this._textureSemanticsDic).length; this.uniformTextureSamplerDic[uniformName] = {}; this.uniformTextureSamplerDic[uniformName].textureUnitIndex = index; this.uniformTextureSamplerDic[uniformName].textureName = texture.userFlavorName; this._textureSemanticsDic[texturePurpose] = uniformName; } } getTextureNumAttachedShader() { return Object.keys(this._textureSemanticsDic).length; } set isAlphaTest(flg){ this._isAlphaTestEnable = flg; } get isAlphaTest() { return this._isAlphaTestEnable; } set alphaCutoff(value) { this._alphaCutoff = value; } get alphaCutoff() { return this._alphaCutoff; } } GLBoost$1['L_AbstractMaterial'] = L_AbstractMaterial; /* */ class ClassicMaterial$1 extends L_AbstractMaterial { constructor(glBoostContext) { super(glBoostContext); this._wireframeWidthRelativeScale = 1.0; this._baseColor = new Vector4$1(1.0, 1.0, 1.0, 1.0); this._diffuseColor = new Vector4$1(1.0, 1.0, 1.0, 1.0); this._specularColor = new Vector4$1(0.5, 0.5, 0.5, 1.0); this._ambientColor = new Vector4$1(0.25, 0.25, 0.25, 1.0); } get wireframeWidthRelativeScale() { return this._wireframeWidthRelativeScale; } clone() { super.clone(); material._baseColor = this._baseColor; material._diffuseColor = this._diffuseColor; material._specularColor = this._specularColor; material._ambientColor = this._ambientColor; } set baseColor(vec ) { if (!vec) { return; } this._baseColor = vec; this._updateCount(); } get baseColor() { return this._baseColor; } set diffuseColor(vec ) { if (!vec) { return; } this._diffuseColor = vec; this._updateCount(); } get diffuseColor() { return this._diffuseColor; } set specularColor(vec ) { if (!vec) { return; } this._specularColor = vec; this._updateCount(); } get specularColor() { return this._specularColor; } set ambientColor(vec ) { if (!vec) { return; } this._ambientColor = vec; this._updateCount(); } get ambientColor() { return this._ambientColor; } } GLBoost$1['ClassicMaterial'] = ClassicMaterial$1; class PBRPrincipledShaderSource { FSDefine_PBRPrincipledShaderSource(in_, f, lights, material, extraData) { let shaderText = ''; shaderText += 'uniform vec2 uMetallicRoughnessFactors;\n'; shaderText += 'uniform vec3 uBaseColorFactor;\n'; shaderText += 'uniform vec2 uOcclusionFactors;'; shaderText += 'uniform vec3 uEmissiveFactor;'; shaderText += 'uniform sampler2D uMetallicRoughnessTexture;\n'; const occlusionTexture = material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_OCCLUSION); if (occlusionTexture) { shaderText += 'uniform sampler2D uOcclusionTexture;\n'; } const emissiveTexture = material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_EMISSIVE); if (emissiveTexture) { shaderText += 'uniform sampler2D uEmissiveTexture;\n'; } const diffuseEnvCubeTexture = material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_IBL_DIFFUSE_ENV_CUBE); if (diffuseEnvCubeTexture) { shaderText += 'uniform sampler2D uBrdfLUTTexture;\n'; shaderText += 'uniform samplerCube uDiffuseEnvTexture;\n'; shaderText += 'uniform samplerCube uSpecularEnvTexture;\n'; shaderText += 'uniform vec3 uIBLParameters;\n'; // Ka * amount of ambient lights } shaderText += 'uniform vec4 ambient;\n'; // Ka * amount of ambient lights const sampler2D = this._sampler2DShadow_func(); const lightNumExceptAmbient = lights.filter((light)=>!light.isTypeAmbient()).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSMethodDefine_PBRPrincipledShaderSource(f, lights, material, extraData) { let shaderText = ''; shaderText += ` const float M_PI = 3.141592653589793; const float c_MinRoughness = 0.04; `; shaderText += ` float angular_n_h(float NH) { return acos(NH); } `; shaderText += ` float sqr(float x) { return x*x; } `; shaderText += ` float d_phong(float NH, float c1) { return pow( cos(acos(NH)) , c1 ); } `; shaderText += ` // GGX NDF float d_ggx(float NH, float alphaRoughness) { float roughnessSqr = alphaRoughness * alphaRoughness; float f = (roughnessSqr - 1.0) * NH * NH + 1.0; return roughnessSqr / (M_PI * f * f); } `; shaderText += ` float d_torrance_reiz(float NH, float c3) { float CosSquared = NH*NH; float TanSquared = (1.0 - CosSquared)/CosSquared; //return (1.0/M_PI) * sqr(c3/(CosSquared * (c3*c3 + TanSquared))); // gamma = 2, aka GGX return (1.0/sqrt(M_PI)) * (sqr(c3)/(CosSquared * (c3*c3 + TanSquared))); // gamma = 1, D_Berry } `; shaderText += ` float d_beckmann(float NH, float m) { float co = 1.0 / (4.0 * m * m * NH * NH * NH * NH); float expx = exp((NH * NH - 1.0) / (m * m * NH * NH)); return co * expx; } `; shaderText += ` // the same as glTF WebGL sample // https://github.com/KhronosGroup/glTF-WebGL-PBR/blob/88eda8c5358efe03128b72b6c5f5f6e5b6d023e1/shaders/pbr-frag.glsl#L188 // That is, Unreal Engine based approach, but modified to use alphaRoughness (squared artist's roughness parameter), // and based on 'Separable Masking and Shadowing' approximation (propesed by Christophe Schlick) // https://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf float g_shielding(float NL, float NV, float alphaRoughness) { float r = alphaRoughness; // Local Shadowing using "Schlick-Smith" Masking Function float localShadowing = 2.0 * NL / (NL + sqrt(r * r + (1.0 - r * r) * (NL * NL))); // Local Masking using "Schlick-Smith" Masking Function float localMasking = 2.0 * NV / (NV + sqrt(r * r + (1.0 - r * r) * (NV * NV))); return localShadowing * localMasking; } `; shaderText += ` // The Schlick Approximation to Fresnel vec3 fresnel(vec3 f0, float LH) { return vec3(f0) + (vec3(1.0) - f0) * pow(1.0 - LH, 5.0); } `; shaderText += ` vec3 cook_torrance_specular_brdf(float NH, float NL, float NV, vec3 F, float alphaRoughness) { float D = d_ggx(NH, alphaRoughness); float G = g_shielding(NL, NV, alphaRoughness); return vec3(D)*vec3(G)*F/vec3(4.0*NL*NV); } `; shaderText += ` vec3 diffuse_brdf(vec3 albedo) { return albedo / M_PI; } `; shaderText += ` vec3 srgbToLinear(vec3 srgbColor) { return pow(srgbColor, vec3(2.2)); } `; shaderText += ` vec3 linearToSrgb(vec3 linearColor) { return pow(linearColor, vec3(1.0/2.2)); } `; const diffuseEnvCubeTexture = material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_IBL_DIFFUSE_ENV_CUBE); if (diffuseEnvCubeTexture) { shaderText += ` vec3 IBLContribution(vec3 n, float NV, vec3 reflection, vec3 albedo, vec3 F0, float userRoughness) { float mipCount = uIBLParameters.x; float lod = (userRoughness * mipCount); vec3 brdf = srgbToLinear(texture2D(uBrdfLUTTexture, vec2(NV, 1.0 - userRoughness)).rgb); vec3 diffuseLight = srgbToLinear(textureCube(uDiffuseEnvTexture, n).rgb); `; const gl = this._glBoostSystem._glContext.gl; const lodExt = gl.getExtension("EXT_shader_texture_lod"); if (lodExt) { shaderText += `vec3 specularLight = srgbToLinear(textureCubeLodEXT(uSpecularEnvTexture, reflection, lod).rgb);`; } else { shaderText += `vec3 specularLight = srgbToLinear(textureCube(uSpecularEnvTexture, reflection).rgb);`; } shaderText += ` vec3 diffuse = diffuseLight * albedo; vec3 specular = specularLight * (F0 * brdf.x + brdf.y); float IBLDiffuseContribution = uIBLParameters.y; float IBLSpecularContribution = uIBLParameters.z; diffuse *= IBLDiffuseContribution; specular *= IBLSpecularContribution; return diffuse + specular; } `; } return shaderText; } FSShade_PBRPrincipledShaderSource(f, gl, lights, material, extraData) { let shaderText = ''; shaderText += ` vec3 surfaceColor = rt0.rgb; rt0 = vec4(0.0, 0.0, 0.0, rt0.a); // BaseColor vec3 baseColor = srgbToLinear(surfaceColor) * uBaseColorFactor.rgb; // Metallic & Roughness float userRoughness = uMetallicRoughnessFactors.y; float metallic = uMetallicRoughnessFactors.x; `; const metallicRoughnessTexture = material.getTextureFromPurpose(GLBoost.TEXTURE_PURPOSE_METALLIC_ROUGHNESS); if (metallicRoughnessTexture) { shaderText += ` vec4 ormTexel = texture2D(uMetallicRoughnessTexture, texcoord); userRoughness = ormTexel.g * userRoughness; metallic = ormTexel.b * metallic; `; } shaderText += ` userRoughness = clamp(userRoughness, c_MinRoughness, 1.0); metallic = clamp(metallic, 0.0, 1.0); float alphaRoughness = userRoughness * userRoughness; // F0 vec3 diffuseMatAverageF0 = vec3(0.04); vec3 F0 = mix(diffuseMatAverageF0, baseColor.rgb, metallic); // Albedo vec3 albedo = baseColor.rgb * (vec3(1.0) - diffuseMatAverageF0); albedo.rgb *= (1.0 - metallic); `; shaderText += ` vec3 viewDirection = normalize(viewPosition_world - v_position_world);\n`; shaderText += ' float NV = clamp(dot(normal, viewDirection), 0.001, 1.0);\n'; for (let i=0; i { MiscUtil.preventDefaultForDesktopOnly(evt); evt.stopPropagation(); let rect = evt.target.getBoundingClientRect(); let clientX = null; let clientY = null; if (evt.clientX) { clientX = evt.clientX; clientY = evt.clientY; } else { clientX = evt.touches[0].clientX; clientY = evt.touches[0].clientY; } this._clickedMouseXOnCanvas = clientX - rect.left; this._clickedMouseYOnCanvas = clientY - rect.top; this._movedMouseYOnCanvas = -1; this._movedMouseXOnCanvas = -1; this._rot_bgn_x = this._rot_x; this._rot_bgn_y = this._rot_y; this._isKeyUp = false; if (typeof evt.buttons !== 'undefined') { this.updateCamera(); } return false; }; this._onMouseUp = (evt) => { this._isKeyUp = true; this._movedMouseYOnCanvas = -1; this._movedMouseXOnCanvas = -1; }; this._onMouseMove = (evt) => { MiscUtil.preventDefaultForDesktopOnly(evt); evt.stopPropagation(); if (this._isKeyUp) { return; } let rect = evt.target.getBoundingClientRect(); let clientX = null; let clientY = null; if (evt.clientX) { clientX = evt.clientX; clientY = evt.clientY; } else { clientX = evt.touches[0].clientX; clientY = evt.touches[0].clientY; } this._movedMouseXOnCanvas = clientX - rect.left; this._movedMouseYOnCanvas = clientY - rect.top; if (typeof evt.buttons !== 'undefined') { let data = evt.buttons; let button_l = ((data & 0x0001) ? true : false); let button_c = ((data & 0x0004) ? true : false); if (button_c) { this._mouse_translate_y = (this._movedMouseYOnCanvas - this._clickedMouseYOnCanvas) / 1000 * this._efficiency; this._mouse_translate_x = (this._movedMouseXOnCanvas - this._clickedMouseXOnCanvas) / 1000 * this._efficiency; let scale = this._lengthOfCenterToEye * this._foyvBias * this._scaleOfTraslation; if (evt.shiftKey) { this._mouseTranslateVec = Vector3.add(this._mouseTranslateVec, Vector3.normalize(this._newEyeToCenterVec).multiply(-this._mouse_translate_y).multiply(scale)); } else { this._mouseTranslateVec = Vector3.add(this._mouseTranslateVec, Vector3.normalize(this._newUpVec).multiply(this._mouse_translate_y).multiply(scale)); } this._mouseTranslateVec = Vector3.add(this._mouseTranslateVec, Vector3.normalize(this._newTangentVec).multiply(this._mouse_translate_x).multiply(scale)); this._clickedMouseYOnCanvas = this._movedMouseYOnCanvas; this._clickedMouseXOnCanvas = this._movedMouseXOnCanvas; } this.updateCamera(); if (!button_l) { return; } } // calc rotation angle let delta_y = (this._movedMouseYOnCanvas - this._clickedMouseYOnCanvas) * this._efficiency; let delta_x = (this._movedMouseXOnCanvas - this._clickedMouseXOnCanvas) * this._efficiency; this._rot_y = this._rot_bgn_y - delta_y; this._rot_x = this._rot_bgn_x - delta_x; // check if rotation angle is within range if (this._verticalAngleThrethold - this._verticalAngleOfVectors < this._rot_y) ; if (this._rot_y < -this._verticalAngleThrethold + this._verticalAngleOfVectors) ; this.updateCamera(); }; this._onMouseWheel = (evt) => { MiscUtil.preventDefaultForDesktopOnly(evt); this.dolly += evt.deltaY / 600; }; this._onContexMenu = (evt) => { if (evt.preventDefault) { MiscUtil.preventDefaultForDesktopOnly(evt); } else { event.returnValue = false; } }; this._onMouseDblClick = (evt) => { if (evt.shiftKey) { this._mouseTranslateVec = new Vector3(0, 0, 0); } else if (evt.ctrlKey) { this._rot_y = 0; this._rot_x = 0; this._rot_bgn_y = 0; this._rot_bgn_x = 0; } this.updateCamera(); }; this.registerEventListeners(eventTargetDom); } registerEventListeners(eventTargetDom = document) { if (eventTargetDom) { if ('ontouchend' in document) { eventTargetDom.addEventListener('touchstart', this._onMouseDown); eventTargetDom.addEventListener('touchend', this._onMouseUp); eventTargetDom.addEventListener('touchmove', this._onMouseMove); } if ('onmouseup' in document) { eventTargetDom.addEventListener('mousedown', this._onMouseDown); eventTargetDom.addEventListener('mouseup', this._onMouseUp); eventTargetDom.addEventListener('mousemove', this._onMouseMove); } if (window.WheelEvent) { eventTargetDom.addEventListener("wheel", this._onMouseWheel); } eventTargetDom.addEventListener('contextmenu', this._onContexMenu, false); eventTargetDom.addEventListener("dblclick", this._onMouseDblClick); } } unregisterEventListeners(eventTargetDom = document) { if (eventTargetDom) { if ('ontouchend' in document) { eventTargetDom.removeEventListener('touchstart', this._onMouseDown); eventTargetDom.removeEventListener('touchend', this._onMouseUp); eventTargetDom.removeEventListener('touchmove', this._onMouseMove); } if ('onmouseup' in document) { eventTargetDom.removeEventListener('mousedown', this._onMouseDown); eventTargetDom.removeEventListener('mouseup', this._onMouseUp); eventTargetDom.removeEventListener('mousemove', this._onMouseMove); } if (window.WheelEvent) { eventTargetDom.removeEventListener("wheel", this._onMouseWheel); } eventTargetDom.removeEventListener('contextmenu', this._onContexMenu, false); eventTargetDom.removeEventListener("dblclick", this._onMouseDblClick); } } _getFovyFromCamera(camera) { if (camera.fovy) { return camera.fovy; } else { return MathUtil.radianToDegree(2 * Math.atan(Math.abs(camera.top - camera.bottom) / (2 * camera.zNear))); } } convert(camera) { let newEyeVec = null; let newCenterVec = null; let newUpVec = null; if (this._isKeyUp || !this._isForceGrab) { this._eyeVec = (this._shiftCameraTo !== null) ? Vector3.add(Vector3.subtract(this._shiftCameraTo, camera.center), camera.eye) : camera.eye; this._centerVec = (this._shiftCameraTo !== null) ? this._shiftCameraTo : camera.center; this._upVec = camera.up; } let fovy = this._getFovyFromCamera(camera); if (this._isSymmetryMode) { let centerToEyeVec = Vector3.subtract(this._eyeVec, this._centerVec).multiply(this._wheel_y * 1.0/Math.tan(MathUtil.degreeToRadian(fovy/2.0))); this._lengthOfCenterToEye = centerToEyeVec.length(); let horizontalAngleOfVectors = Vector3.angleOfVectors(new Vector3(centerToEyeVec.x, 0, centerToEyeVec.z), new Vector3(0, 0, 1)); let horizontalSign = Vector3.cross(new Vector3(centerToEyeVec.x, 0, centerToEyeVec.z), new Vector3(0, 0, 1)).y; if (horizontalSign >= 0) { horizontalSign = 1; } else { horizontalSign = -1; } horizontalAngleOfVectors *= horizontalSign; let rotateM_Reset = Matrix33.rotateY(horizontalAngleOfVectors); let rotateM_X = Matrix33.rotateX(this._rot_y); let rotateM_Y = Matrix33.rotateY(this._rot_x); let rotateM_Revert = Matrix33.rotateY(-horizontalAngleOfVectors); let rotateM = Matrix33.multiply(rotateM_Revert, Matrix33.multiply(rotateM_Y, Matrix33.multiply(rotateM_X, rotateM_Reset))); newUpVec = rotateM.multiplyVector(this._upVec); this._newUpVec = newUpVec; newEyeVec = rotateM.multiplyVector(centerToEyeVec).add(this._centerVec); newCenterVec = this._centerVec.clone(); this._newEyeToCenterVec = Vector3.subtract(newCenterVec, newEyeVec); this._newTangentVec = Vector3.cross(this._newUpVec, this._newEyeToCenterVec); newEyeVec.add(this._mouseTranslateVec); newCenterVec.add(this._mouseTranslateVec); let horizonResetVec = rotateM_Reset.multiplyVector(centerToEyeVec); this._verticalAngleOfVectors = Vector3.angleOfVectors(horizonResetVec, new Vector3(0, 0, 1)); let verticalSign = Vector3.cross(horizonResetVec, new Vector3(0, 0, 1)).x; if (verticalSign >= 0) { verticalSign = 1; } else { verticalSign = -1; } //this._verticalAngleOfVectors *= verticalSign; } else { let centerToEyeVec = Vector3.subtract(this._eyeVec, this._centerVec).multiply(this._wheel_y * 1.0/Math.tan(MathUtil.degreeToRadian(fovy/2.0))); let rotateM_X = Matrix33.rotateX(this._rot_y); let rotateM_Y = Matrix33.rotateY(this._rot_x); let rotateM = rotateM_Y.multiply(rotateM_X); newUpVec = rotateM.multiplyVector(this._upVec); this._newUpVec = newUpVec; newEyeVec = rotateM.multiplyVector(centerToEyeVec).add(this._centerVec); newCenterVec = this._centerVec.clone(); this._newEyeToCenterVec = Vector3.subtract(newCenterVec, newEyeVec); this._newTangentVec = Vector3.cross(this._newUpVec, this._newEyeToCenterVec); newEyeVec.add(this._mouseTranslateVec); newCenterVec.add(this._mouseTranslateVec); } const newCenterToEyeLength = Vector3.lengthBtw(newEyeVec, newCenterVec); let newLeft = camera.left; let newRight = camera.right; let newTop = camera.top; let newBottom = camera.bottom; let newZNear = camera.zNear; let newZFar = camera.zFar; let ratio = 1; if (typeof newLeft !== 'undefined') { if (typeof this._lengthCenterToCorner !== 'undefined') { //let aabb = this._getTargetAABB(); ratio = camera.zNear / Math.abs(newCenterToEyeLength - this._lengthCenterToCorner); const minRatio = 0.001; if (ratio < minRatio) { ratio = minRatio; } let scale = 1 / ratio; newLeft *= scale; newRight *= scale; newTop *= scale; newBottom *= scale; newZFar *= scale; newZNear *= scale; } } if (this._target) { newZFar = camera.zNear + Vector3.subtract(newCenterVec, newEyeVec).length(); newZFar += this._getTargetAABB().lengthCenterToCorner * this._zFarAdjustingFactorBasedOnAABB; } this._foyvBias = Math.tan(MathUtil.degreeToRadian(fovy/2.0)); return [newEyeVec, newCenterVec, newUpVec, newZNear, newZFar, newLeft, newRight, newTop, newBottom]; } _getTargetAABB() { let targetAABB = null; // if (typeof this._target.updateAABB !== 'undefined') { // targetAABB = this._target.updateAABB(); // } else { targetAABB = this._target.AABB; // } return targetAABB; } _updateTargeting(camera, eyeVec, centerVec, upVec, fovy) { if (this._target === null) { return [eyeVec, centerVec, upVec]; } let targetAABB = this._getTargetAABB(); const cameraZNearPlaneHeight = camera.top - camera.bottom; this._lengthCenterToCorner = targetAABB.lengthCenterToCorner; this._lengthCameraToObject = targetAABB.lengthCenterToCorner / Math.sin((fovy*Math.PI/180)/2) * this._scaleOfLengthCameraToCenter; //this._lengthCameraToObject = targetAABB.lengthCenterToCorner * (targetAABB.sizeY/cameraZNearPlaneHeight) / Math.sin((fovy*Math.PI/180)/2) * this._scaleOfLengthCameraToCenter; let newCenterVec = targetAABB.centerPoint; let centerToCameraVec = Vector3.subtract(eyeVec, centerVec); let centerToCameraVecNormalized = Vector3.normalize(centerToCameraVec); let newEyeVec = Vector3.multiply(centerToCameraVecNormalized, this._lengthCameraToObject).add(newCenterVec); let newUpVec = null; if (camera instanceof M_AbstractCamera) { let mat = camera.inverseWorldMatrixWithoutMySelf; newEyeVec = new Vector3(mat.multiplyVector(new Vector4$1(newEyeVec.x, newEyeVec.y, newEyeVec.z, 1))); newCenterVec = new Vector3(mat.multiplyVector(new Vector4$1(newCenterVec.x, newCenterVec.y, newCenterVec.z, 1))); newUpVec = new Vector3(mat.multiplyVector(new Vector4$1(upVec.x, upVec.y, upVec.z, 1))); } else { newUpVec = upVec; } return [newEyeVec, newCenterVec, newUpVec] } tryReset() { if (this._doResetWhenCameraSettingChanged) { if (this._isKeyUp) { this._rot_y = 0; this._rot_x = 0; this._rot_bgn_y = 0; this._rot_bgn_x = 0; } } } reset() { this._rot_y = 0; this._rot_x = 0; this._rot_bgn_y = 0; this._rot_bgn_x = 0; this._wheel_y = 1; this._mouseTranslateVec = new Vector3(0, 0, 0); this._camaras.forEach(function (camera) { camera._needUpdateView(false); }); } updateTargeting() { this._camaras.forEach((camera)=>{ let vectors = this._updateTargeting(camera, camera.eye, camera.center, camera.up, this._getFovyFromCamera(camera)); camera.eye = vectors[0]; camera.center = vectors[1]; camera.up = vectors[2]; }); } updateCamera() { this._camaras.forEach(function (camera) { camera._needUpdateView(false); camera._needUpdateProjection(); }); } addCamera(camera) { this._camaras.add(camera); } set target(object) { this._target = object; this.updateTargeting(); } get target() { return this._target; } set zFarAdjustingFactorBasedOnAABB(value) { this._zFarAdjustingFactorBasedOnAABB = value; } get zFarAdjustingFactorBasedOnAABB() { return this._zFarAdjustingFactorBasedOnAABB; } set shiftCameraTo(value) { this._shiftCameraTo = value; } get shiftCameraTo() { return this._shiftCameraTo; } resetDolly() { this.dolly = 1; this.updateCamera(); } set dolly(value) { this._wheel_y = value; this._wheel_y = Math.min(this._wheel_y, 3); this._wheel_y = Math.max(this._wheel_y, 0.01); this.updateCamera(); } get dolly() { return this._wheel_y; } get rotX() { return this._rot_x; } set rotX(value) { this._rot_x = value; this._rot_bgn_x = 0; this._camaras.forEach(function (camera) { camera._needUpdateView(true); camera._needUpdateProjection(); }); } get rotY() { return this._rot_y; } set rotY(value) { this._rot_y = value; this._rot_bgn_y = 0; this._camaras.forEach(function (camera) { camera._needUpdateView(true); camera._needUpdateProjection(); }); } get allInfo() { const info = {}; info.rotY = this.rotY; info.rotX = this.rotX; info.dolly = this.dolly; info.shiftCameraTo = this.shiftCameraTo; info.zFarAdjustingFactorBasedOnAABB = this.zFarAdjustingFactorBasedOnAABB; info.target = this.target; return info; } set allInfo(arg) { let json = arg; if (typeof arg === "string") { json = JSON.parse(arg); } for(let key in json) { if(json.hasOwnProperty(key) && key in this) { if (key === "quaternion") { this[key] = MathClassUtil.cloneOfMathObjects(MathClassUtil.arrayToQuaternion(json[key])); } else { this[key] = MathClassUtil.cloneOfMathObjects(MathClassUtil.arrayToVectorOrMatrix(json[key])); } } } } } GLBoost$1['L_CameraController'] = L_CameraController; class L_WalkThroughCameraController extends GLBoostObject { constructor(glBoostContext, options = { eventTargetDom: document, horizontalSpeed: 1, turnSpeed: 5, mouseWheelSpeedScale: 0.3, inverseVirticalRotating: false, inverseHorizontalRotating: false }) { super(glBoostContext); this._camaras = new Set(); this._horizontalSpeed = options.horizontalSpeed; this._virticalSpeed = options.virticalSpeed; this._turnSpeed = options.turnSpeed; this._mouseWheelSpeedScale = options.mouseWheelSpeedScale; this._inverseVirticalRotating = options.inverseVirticalRotating; this._inverseHorizontalRotating = options.inverseHorizontalRotating; this.reset(); this._onKeydown = (e)=> { this._isKeyDown = true; this._lastKeyCode = e.keyCode; this.updateCamera(); }; this._onKeyup = (e)=> { this._isKeyDown = false; this._lastKeyCode = null; }; const eventTargetDom = options.eventTargetDom; this.registerEventListeners(eventTargetDom); } updateCamera() { this._camaras.forEach(function (camera) { camera._needUpdateView(false); camera._needUpdateProjection(); }); } registerEventListeners(eventTargetDom = document) { if (eventTargetDom) { document.addEventListener('keydown', this._onKeydown); document.addEventListener('keyup', this._onKeyup); if ('ontouchend' in document) { eventTargetDom.addEventListener('touchstart', this._mouseDown.bind(this)); document.addEventListener('touchend', this._mouseUp.bind(this)); eventTargetDom.addEventListener('touchmove', this._mouseMove.bind(this)); } if ('onmouseup' in document) { eventTargetDom.addEventListener('mousedown', this._mouseDown.bind(this)); document.addEventListener('mouseup', this._mouseUp.bind(this)); eventTargetDom.addEventListener('mousemove', this._mouseMove.bind(this)); } if (window.WheelEvent) { eventTargetDom.addEventListener('wheel', this._mouseWheel.bind(this)); } } } unregisterEventListeners(eventTargetDom = document) { if (eventTargetDom) { document.removeEventListener('keydown', this._onKeydown); document.removeEventListener('keyup', this._onKeyup); if ('ontouchend' in document) { eventTargetDom.removeEventListener('touchstart', this._mouseDown.bind(this)); document.removeEventListener('touchend', this._mouseUp.bind(this)); eventTargetDom.removeEventListener('touchmove', this._mouseMove).bind(this); } if ('onmouseup' in document) { eventTargetDom.removeEventListener('mousedown', this._mouseDown.bind(this)); document.removeEventListener('mouseup', this._mouseUp.bind(this)); eventTargetDom.removeEventListener('mousemove', this._mouseMove.bind(this)); } if (window.WheelEvent) { eventTargetDom.removeEventListener('wheel', this._mouseWheel.bind(this)); } } } _mouseWheel(e) { if (this._currentDir === null) { return; } const delta = e.wheelDelta * this._mouseWheelSpeedScale; const horizontalDir = (new Vector3(this._currentDir.x, 0, this._currentDir.z)).normalize(); this._currentPos.add(Vector3.multiply(horizontalDir, delta)); this._currentCenter.add(Vector3.multiply(horizontalDir, delta)); } _mouseDown(evt) { MiscUtil.preventDefaultForDesktopOnly(evt); evt.stopPropagation(); this._isMouseDown = true; let rect = evt.target.getBoundingClientRect(); this._clickedMouseXOnCanvas = evt.clientX - rect.left; this._clickedMouseYOnCanvas = evt.clientY - rect.top; return false; } _mouseMove(evt) { MiscUtil.preventDefaultForDesktopOnly(evt); evt.stopPropagation(); if (!this._isMouseDown) { return; } let rect = evt.target.getBoundingClientRect(); this._draggedMouseXOnCanvas = evt.clientX - rect.left; this._draggedMouseYOnCanvas = evt.clientY - rect.top; this._deltaMouseXOnCanvas = this._draggedMouseXOnCanvas - this._clickedMouseXOnCanvas; this._deltaMouseYOnCanvas = this._draggedMouseYOnCanvas - this._clickedMouseYOnCanvas; this._isMouseDrag = true; this.updateCamera(); } _mouseUp(evt) { this._isMouseDown = false; this._isMouseDrag = false; let rect = evt.target.getBoundingClientRect(); this._clickedMouseXOnCanvas = evt.clientX - rect.left; this._clickedMouseYOnCanvas = evt.clientY - rect.top; } tryReset() { } reset() { this._isKeyDown = false; this._lastKeyCode = null; this._currentPos = null; this._currentCenter = null; this._currentDir = null; this._isMouseDown = false; this._isMouseDrag = false; this._draggedMouseXOnCanvas = null; this._draggedMouseYOnCanvas = null; this._deltaMouseXOnCanvas = null; this._deltaMouseYOnCanvas = null; this._mouseXAdjustScale = 0.1; this._mouseYAdjustScale = 0.1; this._deltaY = 0; this._deltaX = 0; this._newDir = Vector3.zero(); this._camaras.forEach(function (camera) { camera._needUpdateView(false); }); } addCamera(camera) { this._camaras.add(camera); } convert(camera) { if (this._currentPos === null) { this._currentPos = camera.eye.clone(); } if (this._currentCenter === null) { this._currentCenter = camera.center.clone(); } if (this._currentDir === null) { this._currentDir = Vector3.subtract(camera.center, camera.eye).normalize(); } let newEyeToCenter = null; const t = this._deltaY / 90; this._newDir.x = this._currentDir.x * (1 - t); this._newDir.y = t; this._newDir.z = this._currentDir.z * (1 - t); this._newDir.normalize(); switch(this._lastKeyCode) { case 87: // w key case 38: // arrow upper key { const horizontalDir = (new Vector3(this._currentDir.x, 0, this._currentDir.z)).normalize(); this._currentPos.add(Vector3.multiply(horizontalDir, this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(horizontalDir, this._horizontalSpeed)); } break; case 65: // a key case 37: // arrow left key { const horizontalDir = (new Vector3(this._currentDir.x, 0, this._currentDir.z)).normalize(); const leftDir = Matrix33.rotateY(90).multiplyVector(horizontalDir); this._currentPos.add(Vector3.multiply(leftDir, this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(leftDir, this._horizontalSpeed)); } break; case 83: // s key case 40: // arrow down key { const horizontalDir = (new Vector3(this._currentDir.x, 0, this._currentDir.z)).normalize(); this._currentPos.add(Vector3.multiply(horizontalDir, -this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(horizontalDir, -this._horizontalSpeed)); } break; case 68: // d key case 39: // arrow right key { const horizontalDir = (new Vector3(this._currentDir.x, 0, this._currentDir.z)).normalize(); const rightDir = Matrix33.rotateY(-90).multiplyVector(horizontalDir); this._currentPos.add(Vector3.multiply(rightDir, this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(rightDir, this._horizontalSpeed)); } break; case 81: // q key { this._currentPos.add(Vector3.multiply(this._newDir, -this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(this._newDir, -this._horizontalSpeed)); } break; case 69: // e key { this._currentPos.add(Vector3.multiply(this._newDir, this._horizontalSpeed)); this._currentCenter.add(Vector3.multiply(this._newDir, this._horizontalSpeed)); } break; case 82: // r key this._currentPos.add(new Vector3(0, this._virticalSpeed, 0)); this._currentCenter.add(new Vector3(0, this._virticalSpeed, 0)); break; case 70: // f key this._currentPos.add(new Vector3(0, -this._virticalSpeed, 0)); this._currentCenter.add(new Vector3(0, -this._virticalSpeed, 0)); break; } if (this._isMouseDrag) { if (this._inverseHorizontalRotating) { this._deltaX = this._deltaMouseXOnCanvas * this._mouseXAdjustScale; } else { this._deltaX = -this._deltaMouseXOnCanvas * this._mouseXAdjustScale; } if (this._inverseVirticalRotating) { this._deltaY += this._deltaMouseYOnCanvas * this._mouseYAdjustScale; } else { this._deltaY += -this._deltaMouseYOnCanvas * this._mouseYAdjustScale; } this._deltaY = Math.max(-120, Math.min(50, this._deltaY)); this._currentDir = Matrix33.rotateY(this._deltaX).multiplyVector(this._currentDir); newEyeToCenter = Matrix33.rotateY(this._deltaX).multiplyVector(Vector3.subtract(this._currentCenter, this._currentPos)); newEyeToCenter.x = newEyeToCenter.x * (1 - t); newEyeToCenter.y = t; newEyeToCenter.z = newEyeToCenter.z * (1 - t); newEyeToCenter.normalize(); this._currentCenter = Vector3.add(this._currentPos, newEyeToCenter); this._clickedMouseXOnCanvas = this._draggedMouseXOnCanvas; this._clickedMouseYOnCanvas = this._draggedMouseYOnCanvas; this._deltaMouseXOnCanvas = 0; this._deltaMouseYOnCanvas = 0; } let newLeft = camera.left; let newRight = camera.right; let newTop = camera.top; let newBottom = camera.bottom; return [this._currentPos, this._currentCenter, camera.up.clone(), camera.zNear, camera.zFar, newLeft, newRight, newTop, newBottom]; } getDirection() { return (this._currentCenter !== null) ? this._newDir.clone() : null; } set horizontalSpeed(value) { this._horizontalSpeed = value; } get horizontalSpeed() { return this._horizontalSpeed; } set virticalSpeed(value) { this._virticalSpeed = value; } get virticalSpeed() { return this._virticalSpeed; } get allInfo() { const info = {}; info.virticalSpeed = this.virticalSpeed; info.horizontalSpeed = this.horizontalSpeed; info._turnSpeed = this._turnSpeed; info.shiftCameraTo = this.shiftCameraTo; info.zFarAdjustingFactorBasedOnAABB = this.zFarAdjustingFactorBasedOnAABB; info.target = this.target; if (this._currentPos) { info._currentPos = this._currentPos.clone(); } if (this._currentCenter) { info._currentCenter = this._currentCenter.clone(); } if (this._currentDir) { info._currentDir = this._currentDir.clone(); } info._deltaY = this._deltaY; info._newDir = this._newDir.clone(); return info; } set allInfo(arg) { let json = arg; if (typeof arg === "string") { json = JSON.parse(arg); } for(let key in json) { if(json.hasOwnProperty(key) && key in this) { if (key === "quaternion") { this[key] = MathClassUtil.cloneOfMathObjects(MathClassUtil.arrayToQuaternion(json[key])); } else { this[key] = MathClassUtil.cloneOfMathObjects(MathClassUtil.arrayToVectorOrMatrix(json[key])); } } } } } GLBoost$1['L_WalkThroughCameraController'] = L_WalkThroughCameraController; class MutableTexture extends AbstractTexture { constructor(glBoostContext, width, height, level = 0, internalFormat = 0x1908, // gl.RGBA format = 0x1908, //gl.RGBA type = 0x1401, // gl.UNSIGNED_BYTE magFileter = 0x2601, //gl.LINEAR minFilter = 0x2601, //gl.LINEAR wrapS = 0x812F, // gl.CLAMP_TO_EDGE wrapT = 0x812F) { // gl.CLAMP_TO_EDGE super(glBoostContext); this._isTextureReady = false; this._texture = null; this._width = width; this._height = height; this._fbo = null; this._colorAttachmentId = null; this._depthAttachmentId = null; var gl = this._glContext.gl; //var glem = GLExtensionsManager.getInstance(gl); this._texture = this._glContext.createTexture(this); gl.bindTexture(gl.TEXTURE_2D, this._texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFileter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); if (GLBoost$1.isThisGLVersion_2(gl) && (internalFormat === 6402 || internalFormat === 33189 || internalFormat === 33190 || internalFormat === 33191) ) { // gl.DEPTH_COMPONENT gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, gl.LESS); //gl.LEQUAL); } gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, 0, format, type, null); gl.bindTexture(gl.TEXTURE_2D, null); } set colorAttachment(colorAttachmentId) { this._colorAttachmentId = colorAttachmentId; } get colorAttachment() { return this._colorAttachmentId; } set depthAttachment(depthAttachmentId) { this._depthAttachmentId = depthAttachmentId; } get depthAttachment() { return this._depthAttachmentId; } set frameBufferObject(fbo) { this._fbo = fbo; } get frameBufferObject() { return this._fbo; } } class DataUtil { constructor() { } static isNode() { let isNode = (window === void 0 && typeof process !== "undefined" && typeof require !== "undefined"); return isNode; } static btoa(str) { let isNode = DataUtil.isNode(); if (isNode) { let buffer; if (Buffer.isBuffer(str)) { buffer = str; } else { buffer = new Buffer(str.toString(), 'binary'); } return buffer.toString('base64'); } else { return btoa(str) } } static atob(str) { let isNode = DataUtil.isNode(); if (isNode) { return new Buffer(str, 'base64').toString('binary'); } else { return atob(str) } } static base64ToArrayBuffer(dataUri) { let splittedDataUri = dataUri.split(','); let type = splittedDataUri[0].split(':')[1].split(';')[0]; let byteString = DataUtil.atob(splittedDataUri[1]); let byteStringLength = byteString.length; let arrayBuffer = new ArrayBuffer(byteStringLength); let uint8Array = new Uint8Array(arrayBuffer); for (let i = 0; i < byteStringLength; i++) { uint8Array[i] = byteString.charCodeAt(i); } return arrayBuffer; } static arrayBufferToString(arrayBuffer) { if (typeof TextDecoder !== 'undefined') { let textDecoder = new TextDecoder(); return textDecoder.decode(arrayBuffer); } else { let bytes = new Uint8Array(arrayBuffer); let result = ""; let length = bytes.length; for (let i = 0; i < length; i++) { result += String.fromCharCode(bytes[i]); } return result; } } static stringToBase64(str) { let b64 = null; b64 = DataUtil.btoa(str); return b64; } static UInt8ArrayToDataURL(uint8array, width, height) { let canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; let ctx = canvas.getContext("2d"); let imageData = ctx.createImageData(width, height); for(let i = 0; i < imageData.data.length; i+=4) { /* imageData.data[i + 0] = uint8array[imageData.data.length - i + 0]; imageData.data[i + 1] = uint8array[imageData.data.length - i + 1]; imageData.data[i + 2] = uint8array[imageData.data.length - i + 2]; imageData.data[i + 3] = uint8array[imageData.data.length - i + 3]; */ imageData.data[i + 0] = uint8array[(height - Math.floor(i/(4*width)))*(4*width) + i%(4*width) + 0]; imageData.data[i + 1] = uint8array[(height - Math.floor(i/(4*width)))*(4*width) + i%(4*width) + 1]; imageData.data[i + 2] = uint8array[(height - Math.floor(i/(4*width)))*(4*width) + i%(4*width) + 2]; imageData.data[i + 3] = uint8array[(height - Math.floor(i/(4*width)))*(4*width) + i%(4*width) + 3]; } ctx.putImageData(imageData,0,0); canvas.remove(); return canvas.toDataURL("image/png"); } static loadResourceAsync(resourceUri, isBinary, resolveCallback, rejectCallback) { return new Promise((resolve, reject)=> { let isNode = DataUtil.isNode(); if (isNode) { let fs = require('fs'); let args = [resourceUri]; let func = (err, response) => { if (err) { if (rejectCallback) { rejectCallback(reject, err); } return; } if (isBinary) { let buffer = new Buffer(response, 'binary'); let uint8Buffer = new Uint8Array(buffer); response = uint8Buffer.buffer; } resolveCallback(resolve, response); }; if (isBinary) { args.push(func); } else { args.push('utf8'); args.push(func); } fs.readFile.apply(fs, args); } else { let xmlHttp = new XMLHttpRequest(); if (isBinary) { xmlHttp.responseType = "arraybuffer"; xmlHttp.onload = (oEvent) => { let response = null; if (isBinary) { response = xmlHttp.response; } else { response = xmlHttp.responseText; } resolveCallback(resolve, response); }; } else { xmlHttp.onreadystatechange = ()=> { if (xmlHttp.readyState === 4 && (Math.floor(xmlHttp.status/100) === 2 || xmlHttp.status === 0)) { let response = null; if (isBinary) { response = xmlHttp.response; } else { response = xmlHttp.responseText; } resolveCallback(resolve, response); } else { if (rejectCallback) { rejectCallback(reject, xmlHttp.status); } } }; } xmlHttp.open("GET", resourceUri, true); xmlHttp.send(null); } }); } } GLBoost$1['DataUtil'] = DataUtil; class Texture extends AbstractTexture { constructor(glBoostContext, src, userFlavorName, parameters = null) { super(glBoostContext); this._isTextureReady = false; this._texture = null; if (typeof userFlavorName === 'undefined' || userFlavorName === null) { this.userFlavorName = this._instanceName; } else { this.userFlavorName = userFlavorName; } this._parameters = (parameters) ? parameters : {}; if (typeof src === 'undefined' || src === null) ; else if (typeof src === 'string') { this.generateTextureFromUri(src); } else if (src instanceof Image) { this.generateTextureFromImage(src); } else { this._generateTextureFromImageData(src); } } _getParameter(paramNumber) { let isParametersExist = false; if (this._parameters) { isParametersExist = true; } let params = this._parameters; let paramName = GLBoost$1.getNameOfGLBoostConstant(paramNumber); let ret = null; switch (paramNumber) { case GLBoost$1['UNPACK_FLIP_Y_WEBGL']: case GLBoost$1['UNPACK_PREMULTIPLY_ALPHA_WEBGL']: case GLBoost$1['TEXTURE_MAG_FILTER']: case GLBoost$1['TEXTURE_MIN_FILTER']: case GLBoost$1['TEXTURE_WRAP_S']: case GLBoost$1['TEXTURE_WRAP_T']: if (isParametersExist && params[paramName]) { ret = params[paramName]; } break; } return ret; } _getParamWithAlternative(paramNumber, alternative) { return MiscUtil.getTheValueOrAlternative(this._getParameter(paramNumber), alternative); } generateTextureFromUri(imageUri, isKeepBound = false) { return new Promise((resolve, reject)=> { let isNode = DataUtil.isNode(); if (isNode) { let getPixels = require("get-pixels"); let results = getPixels(imageUri, (err, pixels) => { if (err) { console.log("Bad image path"); reject(); return; } this._width = pixels.shape[0]; this._height = pixels.shape[1]; let texture = this._generateTextureInnerWithArrayBufferView(pixels.data, this._width, this._height, isKeepBound); this._texture = texture; this._isTextureReady = true; resolve(); }); } else { this._img = new Image(); if (!imageUri.match(/^data:/)) { this._img.crossOrigin = 'Anonymous'; } this._img.onload = () => { let imgCanvas = this._getResizedCanvas(this._img); this._width = imgCanvas.width; this._height = imgCanvas.height; let texture = this._generateTextureInner(imgCanvas, isKeepBound); this._texture = texture; this._isTextureReady = true; resolve(); }; this._img.src = imageUri; } }); } generateTextureFromImage(img) { let imgCanvas = this._getResizedCanvas(img); this._width = imgCanvas.width; this._height = imgCanvas.height; let texture = this._generateTextureInner(imgCanvas, false); this._texture = texture; this._isTextureReady = true; } _generateTextureFromImageData(imageData) { var gl = this._glContext.gl; var glem = GLExtensionsManager.getInstance(this._glContext); var imgCanvas = this._getResizedCanvas(imageData); this._width = imgCanvas.width; this._height = imgCanvas.height; var texture = this._generateTextureInner(imgCanvas, false); this._texture = texture; this._isTextureReady = true; this._img = imageData; this._onLoad(); } _generateTextureInnerWithArrayBufferView(imgCanvas, width, height, isKeepBound) { var gl = this._glContext.gl; var glem = GLExtensionsManager.getInstance(this._glContext); var texture = this._glContext.createTexture(this); gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._getParamWithAlternative(GLBoost$1.UNPACK_FLIP_Y_WEBGL, false)); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._getParamWithAlternative(GLBoost$1.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false)); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imgCanvas); if (this._isPowerOfTwoTexture()) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._getParamWithAlternative(GLBoost$1.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)); if (glem.extTFA) { gl.texParameteri(gl.TEXTURE_2D, glem.extTFA.TEXTURE_MAX_ANISOTROPY_EXT, 4); } } gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._getParamWithAlternative(GLBoost$1.TEXTURE_MAG_FILTER, gl.LINEAR)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._getParamWithAlternative(GLBoost$1.TEXTURE_WRAP_S, gl.REPEAT)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._getParamWithAlternative(GLBoost$1.TEXTURE_WRAP_T, gl.REPEAT)); gl.generateMipmap(gl.TEXTURE_2D); if (!isKeepBound) { gl.bindTexture(gl.TEXTURE_2D, null); } return texture; } _generateTextureInner(imgCanvas, isKeepBound) { var gl = this._glContext.gl; var glem = GLExtensionsManager.getInstance(this._glContext); var texture = this._glContext.createTexture(this); gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._getParamWithAlternative(GLBoost$1.UNPACK_FLIP_Y_WEBGL, false)); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._getParamWithAlternative(GLBoost$1.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false)); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imgCanvas); if (this._isPowerOfTwoTexture()) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._getParamWithAlternative(GLBoost$1.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)); if (glem.extTFA) { gl.texParameteri(gl.TEXTURE_2D, glem.extTFA.TEXTURE_MAX_ANISOTROPY_EXT, 4); } } gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._getParamWithAlternative(GLBoost$1.TEXTURE_MAG_FILTER, gl.LINEAR)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._getParamWithAlternative(GLBoost$1.TEXTURE_WRAP_S, gl.REPEAT)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._getParamWithAlternative(GLBoost$1.TEXTURE_WRAP_T, gl.REPEAT)); gl.generateMipmap(gl.TEXTURE_2D); if (!isKeepBound) { gl.bindTexture(gl.TEXTURE_2D, null); } return texture; } _onLoad() { } get isTextureReady() { return this._isTextureReady; } get isImageAssignedForTexture() { return typeof this._img == 'undefined'; } } GLBoost$1['Texture'] = Texture; class PhinaTexture extends Texture { constructor(glBoostContext, width, height, fillStyle, parameters = null) { super(glBoostContext, null, null, parameters); this._parameters['UNPACK_FLIP_Y_WEBGL'] = true; this._width = width; this._height = height; this._fillStyle = fillStyle; this._phinaObjects = []; this._setUpOffscreen(); } _setUpOffscreen() { this._offscreen = phina.display.OffScreenLayer({ width: this.width, height: this.height, fillStyle: this._fillStyle }); this._offscreen.reset(); } addPhinaObject(object) { this._phinaObjects.push(object); return this; } addPhinaObjects(objects) { this._phinaObjects = this._phinaObjects.concat(objects); return this; } setPhinaObjects(objects) { this._phinaObjects = objects.concat(); return this; } clearPhinaObjects() { this._phinaObjects.length = 0; return this; } renderPhinaObjects() { for (let i=0; i { for (let i=0; i{ gl.texImage2D(cubemapSide, i, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);}; } }; loadImageToGPU(posXimages, gl.TEXTURE_CUBE_MAP_POSITIVE_X); loadImageToGPU(negXimages, gl.TEXTURE_CUBE_MAP_NEGATIVE_X); loadImageToGPU(posYimages, gl.TEXTURE_CUBE_MAP_POSITIVE_Y); loadImageToGPU(negYimages, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y); loadImageToGPU(posZimages, gl.TEXTURE_CUBE_MAP_POSITIVE_Z); loadImageToGPU(negZimages, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z); } async generateTextureFromBaseUri(baseUri, mipLevelNum) { return new Promise((resolve, reject)=> { var texture = this._glContext.createTexture(this); this._texture = texture; const gl = this._glContext.gl; let loadedCount = 0; gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); if (mipLevelNum >= 2) { gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); } else { gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); } const onLoadEachCubeImage = (texture, face, image, i)=> { return ()=> { gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); gl.texImage2D(face, i, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); loadedCount++; if (loadedCount === 6) { this._isTextureReady = true; resolve(this); } }; }; for (let i = 0; i < mipLevelNum; i++) { let faces = [ [baseUri + "_right_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_X], [baseUri + "_left_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_X], [baseUri + "_top_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Y], [baseUri + "_bottom_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y], [baseUri + "_front_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_POSITIVE_Z], [baseUri + "_back_" + i + ".jpg", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z] ]; for (var j = 0; j < faces.length; j++) { const face = faces[j][1]; const image = new Image(); image.crossOrigin = "Anonymous"; image.onload = onLoadEachCubeImage(texture, face, image, i); image.src = faces[j][0]; } } }); } get isTextureReady() { return this._isTextureReady; } } class VideoTexture extends AbstractTexture { constructor(glBoostContext, userFlavorName) { super(glBoostContext); } async generateTextureFromVideoUri(uri, playButtonDomElement, mutedAutoPlay) { return new Promise((resolve, reject) => { var button = playButtonDomElement; const playAndSetupTexture = () => { video.play(); this._width = video.width; this._height = video.height; let texture = this._generateTextureInner(video, false); this._texture = texture; this._isTextureReady = true; resolve(); }; // input が押されたらレンダリング開始 button.addEventListener( "click", () => { playAndSetupTexture(); }, true ); const video = document.createElement("video"); video.crossOrigin = "anonymous"; video.setAttribute("playsinline", "playsinline"); if (mutedAutoPlay) { video.autoplay = true; video.muted = true; } video.preload = "auto"; this._video = video; video.addEventListener( "canplaythrough", () => { if (button.value !== "running") { // button.value = 'can play video'; button.disabled = false; playAndSetupTexture(); } }, true ); video.addEventListener( "ended", function() { video.play(); }, true ); video.src = uri; }); } _generateTextureInner(video, isKeepBound) { var gl = this._glContext.gl; var texture = this._glContext.createTexture(this); gl.bindTexture(gl.TEXTURE_2D, texture); //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); //gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); if (!isKeepBound) { gl.bindTexture(gl.TEXTURE_2D, null); } return texture; } get isTextureReady() { return this._isTextureReady; } get isImageAssignedForTexture() { return typeof this._img == "undefined"; } updateTexture() { //gl.bindTexture(gl.TEXTURE_2D, this._texture); //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); var gl = this._glContext.gl; gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._video ); } } /* */ class Cube extends Geometry { constructor(glBoostContext , widthVector , vertexColor ) { super(glBoostContext); // if array, convert to vector[2/3/4] widthVector = MathClassUtil.arrayToVector(widthVector); vertexColor = MathClassUtil.arrayToVector(vertexColor); this._setupVertexData(widthVector.divide(2.0), vertexColor); } _setupVertexData(widthVector, vertexColor) { var indices = [ 3, 1, 0, 2, 1, 3, 4, 5, 7, 7, 5, 6, 8, 9, 11, 11, 9, 10, 15, 13, 12, 14, 13, 15, 19, 17, 16, 18, 17, 19, 20, 21, 23, 23, 21, 22 ]; var positions = [ // upper new Vector3(-widthVector.x, widthVector.y, -widthVector.z), new Vector3(widthVector.x, widthVector.y, -widthVector.z), new Vector3(widthVector.x, widthVector.y, widthVector.z), new Vector3(-widthVector.x, widthVector.y, widthVector.z), // lower new Vector3(-widthVector.x, -widthVector.y, -widthVector.z), new Vector3(widthVector.x, -widthVector.y, -widthVector.z), new Vector3(widthVector.x, -widthVector.y, widthVector.z), new Vector3(-widthVector.x, -widthVector.y, widthVector.z), // front new Vector3(-widthVector.x, -widthVector.y, widthVector.z), new Vector3(widthVector.x, -widthVector.y, widthVector.z), new Vector3(widthVector.x, widthVector.y, widthVector.z), new Vector3(-widthVector.x, widthVector.y, widthVector.z), // back new Vector3(-widthVector.x, -widthVector.y, -widthVector.z), new Vector3(widthVector.x, -widthVector.y, -widthVector.z), new Vector3(widthVector.x, widthVector.y, -widthVector.z), new Vector3(-widthVector.x, widthVector.y, -widthVector.z), // right new Vector3(widthVector.x, -widthVector.y, -widthVector.z), new Vector3(widthVector.x, -widthVector.y, widthVector.z), new Vector3(widthVector.x, widthVector.y, widthVector.z), new Vector3(widthVector.x, widthVector.y, -widthVector.z), // left new Vector3(-widthVector.x, -widthVector.y, -widthVector.z), new Vector3(-widthVector.x, -widthVector.y, widthVector.z), new Vector3(-widthVector.x, widthVector.y, widthVector.z), new Vector3(-widthVector.x, widthVector.y, -widthVector.z) ]; var colors = [ new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w), new Vector4$1(vertexColor.x, vertexColor.y, vertexColor.z, vertexColor.w) ]; var texcoords = [ new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) ]; var normals = [ // upper new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), // lower new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), // front new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1), // back new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1), // right new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), // left new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), ]; this.setVerticesData({ position: positions, color: colors, normal: normals, texcoord: texcoords }, [indices]); } } GLBoost$1["Cube"] = Cube; class ArrayUtil { constructor() { } static merge() { var key, result = false; if (arguments && arguments.length > 0) { result = []; for (var i = 0, len = arguments.length;i < len; i++) { if (arguments[i] && typeof arguments[i] === 'object') { for (key in arguments[i]) { if (isFinite(key)) { result.push(arguments[i][key]); } else { result[key] = arguments[i][key]; } } } } } return result; } } class Plane extends Geometry { constructor(glBoostContext, width, height, uSpan, vSpan, customVertexAttributes, isUVRepeat = false) { super(glBoostContext); this._setupVertexData(width, height, uSpan, vSpan, customVertexAttributes, isUVRepeat); } _setupVertexData(width, height, uSpan, vSpan, customVertexAttributes, isUVRepeat) { var positions = []; for(let i=0; i<=vSpan; i++) { for(let j=0; j<=uSpan; j++) { positions.push(new Vector3((j/uSpan - 1/2)*width, 0, (i/vSpan - 1/2)*height)); } } var indices = []; for(let i=0; i * @param width - width of texture * @param height - height of texture * @param textureNum - the number of creation. * @returns an array of created textures. */ createTexturesForRenderTarget(width , height , textureNum ) { var glContext = this.__system._glContext; var gl = glContext.gl; var glem = GLExtensionsManager.getInstance(glContext); // Create FBO var fbo = glContext.createFramebuffer(this.__system); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); fbo.width = width; fbo.height = height; fbo._glboostTextures = []; for(let i=0; i{ var glTexture = texture.glTextureResource; var attachimentId = glem.colorAttachiment(gl, i); texture.colorAttachment = attachimentId; gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0); }); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderBuffer); gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); return fbo._glboostTextures.concat(); } createDepthTexturesForRenderTarget(width , height ) { var glContext = this.__system._glContext; var gl = glContext.gl; var glem = GLExtensionsManager.getInstance(glContext); // Create FBO var fbo = glContext.createFramebuffer(this.__system); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); fbo.width = width; fbo.height = height; /* // Create color RenderBuffer var colorBuffer = gl.createRenderbuffer(); gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fbo.width, fbo.width); */ // Create MutableTexture for Depth Texture let format = gl.DEPTH_COMPONENT; let internalFormat = gl.DEPTH_COMPONENT; let type = gl.UNSIGNED_INT; if (GLBoost$1.isThisGLVersion_2(gl)) { type = gl.UNSIGNED_INT; format = gl.DEPTH_COMPONENT; internalFormat = gl.DEPTH_COMPONENT24; } else if (glem.extDepthTex) { type = glem.extDepthTex.UNSIGNED_INT_24_8_WEBGL; format = gl.DEPTH_STENCIL; internalFormat = gl.DEPTH_STENCIL; } let depthTexture = new MutableTexture(this.__system, fbo.width, fbo.height, 0, internalFormat, format, type, gl.LINEAR, gl.LINEAR, gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE); depthTexture.fbo = fbo; depthTexture.userFlavorName = `DepthTexture_${fbo.width}x${fbo.height}`; /// Attach Buffers // color // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); //gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); // depth var glTexture = depthTexture.glTextureResource; var attachimentId = gl.DEPTH_ATTACHMENT; if (GLBoost$1.isThisGLVersion_2(gl)) { attachimentId = gl.DEPTH_ATTACHMENT; } else if (glem.extDepthTex) { attachimentId = gl.DEPTH_STENCIL_ATTACHMENT; } depthTexture.depthAttachment = attachimentId; gl.framebufferTexture2D(gl.FRAMEBUFFER, attachimentId, gl.TEXTURE_2D, glTexture, 0); // console.log('FBO', gl.checkFramebufferStatus(gl.FRAMEBUFFER)); gl.bindFramebuffer(gl.FRAMEBUFFER, null); return depthTexture; } get belongingCanvasId() { return this.__system._glContext.belongingCanvasId; } set globalStatesUsage(usageMode ) { this.__system._globalStatesUsage = usageMode; } get globalStatesUsage() { return this.__system._globalStatesUsage; } reflectGlobalGLState() { let gl = this.__system._glContext.gl; if (this.currentGlobalStates != null) { this.currentGlobalStates.forEach((state)=>{ gl.enable(state); }); } gl.depthFunc( gl.LEQUAL ); gl.blendEquation( gl.FUNC_ADD ); gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA ); gl.clearDepth( 1 ); gl.clearStencil( 0 ); } disableAllGLState() { let states = [ 3042, // gl.BLEND 2884, // gl.CULL_FACE 2929, // gl.DEPTH_TEST 32823, // gl.POLYGON_OFFSET_FILL 32926, // gl.SAMPLE_ALPHA_TO_COVERAGE ]; let glContext = this.__system._glContext; let gl = glContext.gl; states.forEach((state)=>{ gl.disable(state); }); } set currentGlobalStates(states ) { this.__system._currentGlobalStates = states.concat(); } get currentGlobalStates() { return this.__system._currentGlobalStates; } restoreGlobalStatesToDefault() { this.__system._currentGlobalStates = this.__system._defaultGlobalStates.concat(); } get glBoostMonitor() { return this.__system._glBoostMonitor; } setPropertiesFromJson(arg , queryType = GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME) { let json = arg; if (typeof arg === "string") { json = JSON.parse(arg); } if (!json.targetUserFlavorName) { console.warn(`Faild! This json doesn't include targetInstanceName field!`); return; } let objects = null; if (queryType === GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME) { objects = this.__system._glBoostMonitor.getGLBoostObjectsByUserFlavorName((json.targetUserFlavorName )); } else if (queryType === GLBoost$1.QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR) { const targetInstanceName = (json ).targetInstanceName; const found = this.__system._glBoostMonitor.getGLBoostObject(targetInstanceName); if (found != null && found.userFlavorName === json.targetUserFlavorName) { objects = [found]; } else { objects = []; } } else { const found = this.__system._glBoostMonitor.getGLBoostObject(json.targetInstanceName); objects = [found]; } objects.forEach((obj )=>{obj.setPropertiesFromJson(json);}); return objects; } } GLBoost$1['GLBoostLowContext'] = GLBoostLowContext; // class M_Mesh extends M_Element { constructor(glBoostContext , geometry , material ) { super(glBoostContext); if (geometry) { this.geometry = geometry; } if (material) { this.material = material; } this._transformedDepth = 0; this._outlineGizmo = null; this._isPickable = true; } prepareToRender(expression , existCamera_f , lights ) { this._geometry.prepareToRender(expression, existCamera_f, lights, this._material, this); /* if (this._geometry._materials.length === 0 && this._material) { let shaderInstance = this._geometry.prepareGLSLProgramAndSetVertexNtoMaterial(expression, this._material, 0, existCamera_f, lights); this._geometry._setVertexNtoSingleMaterial(this._material, 0); this._material.shaderInstance = shaderInstance; this._material.shaderInstance.vao = this._geometry._getVAO(); this._geometry.setUpVertexAttribs(this._glContext.gl, shaderInstance._glslProgram, this._geometry._getAllVertexAttribs()); } */ } draw(data ) { this._geometry.draw( { expression: data.expression, lights: data.lights, camera: data.camera, scene: data.renderPass.scene, renderPassIndex: data.renderPassIndex, mesh: this, viewport: data.viewport, isWebVRMode: data.isWebVRMode, webvrFrameData: data.webvrFrameData, forceThisMaterial: data.forceThisMaterial, } ); } set geometry(geometry ) { this._geometry = geometry; geometry._parent = this; M_Mesh._geometries[geometry.toString()] = geometry; } get geometry() { return this._geometry; } set material(material ) { this._material = material; } get material() { return this._material; } bakeTransformToGeometry() { var positions = this._geometry._vertices.position; var mat = this.worldMatrix; let componentN = this._geometry._vertices.components.position; let length = positions.length / componentN; for (let i=0; i 3) { positions[i * componentN+3] = transformedPosVec.w; } } this._geometry._vertices.position = positions; if (this._geometry._vertices.normal) { var normals = this._geometry._vertices.normal; length = normals.length / 3; for (let i=0; i 3) { positions[i * componentN+3] = transformedPosVec.w; } } this._geometry._vertices.position = positions; let mat = this.worldMatrix; if (this._geometry._vertices.normal) { var normals = this._geometry._vertices.normal; length = normals.length / 3; for (let i=0; i 0) { objects = objects.concat(hitChildren); } } return objects; } if (type.name.indexOf("Gizmo") !== -1 && element instanceof M_Element) { let gizmos = element._gizmos; for (let gizmo of gizmos) { if (this._validateByQuery(gizmo, query, queryMeta)) { objects.push(gizmo); } } return objects; } if (type.name.indexOf("Material") !== -1 && element instanceof M_Mesh) { let materials = element.getAppropriateMaterials(); for (let material of materials) { if (material instanceof type) { if (this._validateByQuery(material, query, queryMeta)) { objects.push(material); } } } return objects; } if (type.name.indexOf("Texture") !== -1 && element instanceof M_Mesh) { let materials = element.getAppropriateMaterials(); for (let material of materials) { const textures = material.getTextures(); for (let texture of textures) { if (texture instanceof type) { if (this._validateByQuery(texture, query, queryMeta)) { objects.push(texture); } } } } return objects; } if ( this._validateByQuery(element, query, queryMeta) && element instanceof type ) { return [element]; } return objects; } searchGLBoostObjectsByType(type , element = this) { let objects = []; if (element instanceof M_Group) { let children = element.getChildren(); for (let i = 0; i < children.length; i++) { let hitChildren = this.searchGLBoostObjectsByType(type, children[i]); if (hitChildren.length > 0) { objects = objects.concat(hitChildren); } } return objects; } if (type.name.indexOf("Gizmo") !== -1 && element instanceof M_Element) { let gizmos = element._gizmos; for (let gizmo of gizmos) { objects.push(gizmo); } return objects; } if (type.name.indexOf("Material") !== -1 && element instanceof M_Mesh) { let materials = element.getAppropriateMaterials(); for (let material of materials) { if (material instanceof type) { objects.push(material); } } return objects; } if (type.name.indexOf("Texture") !== -1 && element instanceof M_Mesh) { let materials = element.getAppropriateMaterials(); for (let material of materials) { const textures = material.getTextures(); for (let texture of textures) { if (texture instanceof type) { objects.push(texture); } } } return objects; } if (element instanceof type) { return [element]; } return objects; } getStartAnimationInputValue(inputLineName , element = this) { if (element instanceof M_Group) { let latestInputValue = element.getStartInputValueOfAnimation( inputLineName ); let children = element.getChildren(); for (let i = 0; i < children.length; i++) { let hitChildOrInputValue = this.getStartAnimationInputValue( inputLineName, children[i] ); if (hitChildOrInputValue instanceof M_Element) { let startInputValueOfThisElement = hitChildOrInputValue.getStartInputValueOfAnimation( inputLineName ); if (startInputValueOfThisElement < latestInputValue) { latestInputValue = startInputValueOfThisElement; } } else { let startInputValueOfThisElement = hitChildOrInputValue; if (startInputValueOfThisElement < latestInputValue) { latestInputValue = startInputValueOfThisElement; } } } return latestInputValue; } return element.getStartInputValueOfAnimation(inputLineName); } getEndAnimationInputValue(inputLineName , element = this) { if (element instanceof M_Group) { let latestInputValue = element.getEndInputValueOfAnimation(inputLineName); let children = element.getChildren(); for (let i = 0; i < children.length; i++) { let hitChildOrInputValue = this.getEndAnimationInputValue( inputLineName, children[i] ); if (hitChildOrInputValue instanceof M_Element) { let endInputValueOfThisElement = hitChildOrInputValue.getEndInputValueOfAnimation( inputLineName ); if (endInputValueOfThisElement > latestInputValue) { latestInputValue = endInputValueOfThisElement; } } else { let endInputValueOfThisElement = hitChildOrInputValue; if (endInputValueOfThisElement > latestInputValue) { latestInputValue = endInputValueOfThisElement; } } } return latestInputValue; } else if (!(element.getEndInputValueOfAnimation != null)) { return 0; } return element.getEndInputValueOfAnimation(inputLineName); } /* * Note that it's in world space */ updateAABB() { const that = this; var aabb = (function mergeAABBRecursively(elem) { if (elem instanceof M_Group) { var children = elem.getChildren(); for (let i = 0; i < children.length; i++) { var aabb = mergeAABBRecursively(children[i]); if (aabb instanceof AABB) { elem.AABB.mergeAABB(aabb); } else { console.assert("calculation of AABB error!"); } } if (!elem.AABB.isValid()) { that._logger.out( GLBoost$1.LOG_LEVEL_WARN, GLBoost$1.LOG_TYPE_AABB, true, "This AABB has abnormal values", elem.userFlavorName, elem.AABB ); } return elem.AABB; //return AABB.multiplyMatrix(elem.transformMatrix, elem.AABB); } if (elem instanceof M_Mesh) { let aabb = elem.AABBInWorld; //console.log(aabb.toString()); return aabb; } return null; })(this); this.AABB.mergeAABB(aabb); let newAABB = this.AABB; // this._AABB = aabbInWorld; this._updateAABBGizmo(); return newAABB; } get AABB() { return this._AABB; } clone( clonedOriginalRootElement = this, clonedRootElement = null, onCompleteFuncs = [] ) { let instance = new M_Group(this._glBoostSystem); if (clonedRootElement === null) { clonedRootElement = instance; } this._copy(instance); this._elements.forEach(element => { if (typeof element.clone !== "undefined") { instance._elements.push( element.clone( clonedOriginalRootElement, clonedRootElement, onCompleteFuncs ) ); } else { instance._elements.push(element); } }); onCompleteFuncs.forEach(func => { func(); }); return instance; } _copy(instance) { super._copy(instance); instance._AABB = this._AABB.clone(); instance._isRootJointGroup = this._isRootJointGroup; } set isVisible(flg ) { let collectVisibility = function(elem ) { elem._isVisible = flg; if (elem instanceof M_Group) { let children = elem.getChildren(); children.forEach(function(child) { collectVisibility(child); }); } }; collectVisibility(this); } get isVisible() { return this._isVisible; } setSpecifiedPropertyRecursively(propertyName , value ) { let setValueRecursively = function(elem ) { elem[propertyName] = value; if (elem instanceof M_Group) { let children = elem.getChildren(); children.forEach(function(child) { setValueRecursively(child); }); } }; setValueRecursively(this); } executeSpecifiedFunctionRecursively( func , thisObj , args , childIndexToInsertToArgs = null ) { let execRecursively = function(elem ) { if (childIndexToInsertToArgs != null) { args[childIndexToInsertToArgs] = elem; } func.apply(thisObj, args); if (elem instanceof M_Group) { let children = elem.getChildren(); children.forEach(function(child) { execRecursively(child); }); } }; execRecursively(this); } _updateAABBGizmo() { /* if (this._aabbGizmo === null) { this._aabbGizmo = new M_AABBGizmo(this._glBoostContext); } */ let world_m = this.worldMatrix; let aabbInWorld = AABB.multiplyMatrix(world_m, this._AABB); // this._aabbGizmo.updateGizmoDisplay(aabbInWorld.minPoint, aabbInWorld.maxPoint); } readyForDiscard() { let collectElements = function(elem) { if (elem instanceof M_Group) { const children = elem.getChildren(); for (let i = 0; i < children.length; i++) { collectElements(children[i]); } } else if (elem instanceof M_Element) { // Must be M_Element elem.readyForDiscard(); } else { if ( typeof EffekseerElement !== undefined && elem instanceof EffekseerElement ) { console.log("Nothing to do for discarding at this time."); } console.error("not M_Group nor M_Element"); } }; collectElements(this); this.removeAll(); } rayCast( arg1 , arg2 , camera , viewport , ignoreInstanceNameList ) { const meshes = this.searchElementsByType(M_Mesh); let currentShortestT = Number.MAX_VALUE; let currentShortestIntersectedPosVec3 = null; let selectedMesh = null; for (let mesh of meshes) { if (!mesh.isVisible) { continue; } if (!mesh.isPickable) { continue; } if ( ignoreInstanceNameList && ignoreInstanceNameList.indexOf(mesh.instanceName) !== -1 ) { continue; } let result = null; if (arg1 instanceof Vector3 && arg2 instanceof Vector3) { result = mesh.rayCast(arg1, arg2, camera); } else { result = mesh.rayCast(arg1, arg2, camera, viewport); } if (result === null) { return [null, null]; } const t = result[1]; if (t < currentShortestT) { currentShortestT = t; currentShortestIntersectedPosVec3 = result[0]; selectedMesh = mesh; } } return [currentShortestIntersectedPosVec3, currentShortestT, selectedMesh]; } _needUpdate() { super._needUpdate(); let collectElements = function(elem) { if (elem instanceof M_Group) { const children = elem.getChildren(); for (let i = 0; i < children.length; i++) { collectElements(children[i]); } } else if (elem instanceof M_Mesh) { if (elem._outlineGizmo) { elem._outlineGizmo.updateMatrix(elem); } } }; collectElements(this); } } GLBoost$1["M_Group"] = M_Group; let singleton$4 = Symbol(); class M_GLBoostMonitor extends L_GLBoostMonitor { constructor(enforcer) { super(enforcer); } static getInstance() { if (!this[singleton$4]) { this[singleton$4] = new M_GLBoostMonitor(L_GLBoostMonitor._singletonEnforcer); } return this[singleton$4]; } getGLBoostObjectsFromArgument(arg) { let objects = []; if (typeof arg === 'undefined') { objects = this._glBoostObjects; } else if (typeof (arg) === "string") { for (let key in this._glBoostObjects) { if (this._glBoostObjects.hasOwnProperty(key) && this._glBoostObjects[key].userFlavorName === arg) { objects.push(this._glBoostObjects[key]); break; } } } else { if (arg instanceof GLBoostObject) { objects = [arg]; } } return objects; } getMMeshes(glBoostObjects) { let meshes = []; for (let object of glBoostObjects) { if (object instanceof M_Mesh) { meshes.push(object); } else if (object instanceof M_Group) { meshes = meshes.concat(object.searchElementsByType(GLBoost$1.M_Mesh)); } } meshes = meshes.filter((mesh, i, self) => self.indexOf(mesh) === i); return meshes; } getTriangleCount(userFlavorNameOrGLBoostObject) { let objects = this.getGLBoostObjectsFromArgument(userFlavorNameOrGLBoostObject); let meshes = this.getMMeshes(objects); let count = 0; for (let mesh of meshes) { count += mesh.geometry.getTriangleCount(mesh); } return count; } getVertexCount(userFlavorNameOrGLBoostObject) { let objects = this.getGLBoostObjectsFromArgument(userFlavorNameOrGLBoostObject); let meshes = this.getMMeshes(objects); let count = 0; for (let mesh of meshes) { count += mesh.geometry.getVertexCount(mesh); } return count; } getTextureUserFlavorNames(userFlavorNameOrGLBoostObject) { let objects = this.getGLBoostObjectsFromArgument(userFlavorNameOrGLBoostObject); let meshes = this.getMMeshes(objects); let textureUserFlavorNames = []; for (let mesh of meshes) { let materials = mesh.geometry._getAppropriateMaterials(mesh); for (let i = 0; i{ renderPass._expression = this; }); this._renderPasses = this._renderPasses.concat(renderPasses); } addRenderPass(renderPass) { renderPath._expression = this; this._renderPasses.push(renderPass); } clearRenderPasses() { this._renderPasses.forEach((renderPass)=>{ renderPass._expression = null; }); this._renderPasses.length = 0; } get renderPasses() { return this._renderPasses; } setCurrentAnimationValue(inputName, inputValue) { for (let renderPass of this.renderPasses) { if (renderPass.scene) { renderPass.scene.setCurrentAnimationValue(inputName, inputValue); } } } prepareToRender() { this._renderPasses.forEach((renderPass, index)=>{ renderPass.prepareToRender(this); }); } } GLBoost$1['Expression'] = Expression; class M_FrustumCamera extends M_AbstractCamera { constructor(glBoostContext, toRegister, lookat, perspective) { super(glBoostContext, toRegister); this._lowLevelCamera = new L_FrustumCamera(this, false, lookat, perspective); this._lowLevelCamera._middleLevelCamera = this; } // ===================== delegate to low level class ======================== _needUpdateProjection() { this._lowLevelCamera._needUpdateProjection(); } get updateCountAsCameraProjection() { return this._lowLevelCamera.updateCountAsCameraProjection; } projectionRHMatrix() { return this._lowLevelCamera.projectionRHMatrix(); } set left(value) { this._lowLevelCamera.left = value; } get left() { return this._lowLevelCamera.left; } set right(value) { this._lowLevelCamera.right = value; } get right() { return this._lowLevelCamera.right; } set top(value) { this._lowLevelCamera.top = value; } get top() { return this._lowLevelCamera.top; } set bottom(value) { this._lowLevelCamera.bottom = value; } get bottom() { return this._lowLevelCamera.bottom; } set zNear(value) { this._lowLevelCamera.zNear = value; } get zNear() { return this._lowLevelCamera.zNear; } set zFar(value) { this._lowLevelCamera.zFar = value; } get zFar() { return this._lowLevelCamera.zFar; } get aspect() { return this._lowLevelCamera.aspect; } get fovy() { return this._lowLevelCamera.fovy; } } GLBoost$1['M_FrustumCamera'] = M_FrustumCamera; class M_PerspectiveCamera extends M_AbstractCamera { constructor(glBoostContext, toRegister, lookat, perspective) { super(glBoostContext, toRegister); this._lowLevelCamera = new L_PerspectiveCamera(this, false, lookat, perspective); this._lowLevelCamera._middleLevelCamera = this; } // ===================== delegate to low level class ======================== _needUpdateProjection() { this._lowLevelCamera._needUpdateProjection(); } get updateCountAsCameraProjection() { return this._lowLevelCamera.updateCountAsCameraProjection; } projectionRHMatrix() { return this._lowLevelCamera.projectionRHMatrix(); } set fovy(value) { this._lowLevelCamera.fovy = value; } get fovy() { return this._lowLevelCamera.fovy; } set aspect(value) { this._lowLevelCamera.aspect = value; } get aspect() { return this._lowLevelCamera.aspect; } set zNear(value) { this._lowLevelCamera.zNear = value; } get zNear() { return this._lowLevelCamera.zNear; } set zFar(value) { this._lowLevelCamera.zFar = value; } get zFar() { return this._lowLevelCamera.zFar; } } GLBoost$1['M_PerspectiveCamera'] = M_PerspectiveCamera; class EffekseerElement$1 extends M_Element { constructor(glBoostContext) { super(glBoostContext); this.__effect = null; this.__handle = null; this.__speed = 1; this.__timer = null; } load(uri, playJustAfterLoaded = false, isLoop = false) { return new Promise((resolve, reject)=>{ this.__effect = effekseer.loadEffect(uri, ()=>{ if (playJustAfterLoaded) { if (isLoop) { this.__timer = setInterval(()=>{ this.play(); }, 500); } else { this.play(); } } resolve(this); }); }) } cancelLoop() { clearInterval(this.__timer); } play(isLoop = false) { const __play = ()=>{ // Play the loaded effect this.__handle = effekseer.play(this.__effect); this.update(); }; if (isLoop) { this.__timer = setInterval(__play, 200); } else { __play(); } } update(camera) { if (this.__handle != null) { this.__handle.setMatrix(this.worldMatrix.m); this.__handle.setSpeed(this.__speed); } } set playSpeed(val) { if (this.__handle) { this.__handle.setSpeed(val); } this.__speed = val; } get playSpeed() { return this.__speed; } set translate(vec) { if (this.__handle) { this.__handle.setLocation(vec.x, vec.y, vec.z); } super.translate = vec; } get translate() { return super.translate; } set rotate(vec) { if (this.__handle) { this.__handle.setRotation(vec.x, vec.y, vec.z); } super.rotate = vec; } get rotate() { return super.rotate; } set scale(vec) { if (this.__handle) { this.__handle.setScale(vec.x, vec.y, vec.z); } super.scale = vec; } get scale() { return super.scale; } } class RenderPass extends GLBoostObject { constructor(glBoostContext) { super(glBoostContext); this._scene = null; this._meshes = []; this._preGizmos = []; this._postGizmos = []; this._opacityMeshes = []; this._transparentMeshes = []; this._effekseerElements = []; this._transparentMeshesAsManualOrder = null; this._drawBuffers = [this._glContext.gl.NONE]; this._clearColor = null; // webgl default is [0, 0, 0, 0] this._clearDepth = null; // webgl default is 1.0 this._colorMask = null; // webgl defalult is [true, true, true, true] this._renderTargetColorTextures = []; this._renderTargetDepthTexture = []; this._expression = null; this._viewport = null; this._isRenderTargetAttachedTextures = false; this._isEnableToDraw = true; this._customFunctionWhenPrepareToRender = null; this._customFunctionWhenPreRender = null; this._customFunctionWhenPostRender = null; this._webglStatesAssignDictionaries = []; this._backupWebGLStatesOfMaterials = []; this._shaderParametersAssignDictionaries = []; this._backupShaderParametersOfMaterials = []; this._shaderAssignDictionaries = []; this._backupShadersOfInstances = []; this._newShaderInstance = null; this._oldShaderClass = null; this._backupShaderClassDic = {}; this._doPreRender = true; this._doPostRender = true; this._tag = ''; } set tag(name) { this._tag = name; } get tag() { return this._tag; } get doPreRender() { return this._doPreRender; } set doPreRender(flg) { this._doPreRender = flg; } get doPostRender() { return this._doPostRender; } set doPostRender(flg) { this._doPostRender = flg; } get expression() { return this._expression; } set scene(scene) { this._scene = scene; } get scene() { return this._scene; } get meshes() { return this._meshes; } get opacityMeshes() { return this._opacityMeshes; } get transparentMeshes() { return this._transparentMeshes; } get preGizmos() { return this._preGizmos; } get postGizmos() { return this._postGizmos; } specifyRenderTargetTextures(renderTargetTextures) { var gl = this._glContext.gl; var colorRenderTargetTextures = renderTargetTextures.filter((renderTargetTexture)=>{ if (renderTargetTexture.colorAttachment) { return true; } else { return false; } }); if (colorRenderTargetTextures.length > 0) { this._drawBuffers = []; colorRenderTargetTextures.forEach((texture)=>{ var attachment = texture.colorAttachment; this._drawBuffers.push(attachment); }); this._renderTargetColorTextures = colorRenderTargetTextures; } else { this._drawBuffers = [gl.NONE]; } var depthRenderTargetTextures = renderTargetTextures.filter((renderTargetTexture)=>{ if (renderTargetTexture.depthAttachment) { return true; } else { return false; } }); this._renderTargetDepthTexture = depthRenderTargetTextures[0]; this._isRenderTargetAttachedTextures = true; } get buffersToDraw() { return this.isRenderTargetAttachedTextures ? this._drawBuffers : [this._glContext.gl.BACK]; } set isRenderTargetAttachedTextures(flg) { this._isRenderTargetAttachedTextures = flg; } get isRenderTargetAttachedTextures() { return this._isRenderTargetAttachedTextures; } get fbo() { if (this._renderTargetColorTextures.length > 0) { return this._renderTargetColorTextures[0].fbo; } else if (this._renderTargetDepthTexture) { return this._renderTargetDepthTexture.fbo; } else { return null; } } get viewport() { return this._viewport; } set viewport(vec4) { this._viewport = vec4; } setViewportAsFittingToRenderTarget() { let width; let height; if (this._renderTargetColorTextures.length > 0) { width = this._renderTargetColorTextures[0].width; height = this._renderTargetColorTextures[0].height; } if (this._renderTargetDepthTexture) { width = this._renderTargetDepthTexture.width; height = this._renderTargetDepthTexture.height; } if (typeof width !== 'undefined' && typeof height !== 'undefined') { this._viewport = new Vector4$1(0, 0, width, height); return true; } else { return false; } } get renderTargetColorTextures() { return this._renderTargetColorTextures; } get renderTargetDepthTexture() { return this._renderTargetDepthTexture; } setClearColor(color) { this._clearColor = color; } get clearColor() { return this._clearColor; } setClearDepth(depth) { this._clearDepth = depth; } get clearDepth() { return this._clearDepth; } setColorMask(colorMask) { this._colorMask = colorMask; } get colorMask() { return this._colorMask; } setWebGLStatesAssignDictionaries(dictionaries) { this._webglStatesAssignDictionaries = dictionaries; } setShaderParametersAssignDictionaries(dictionaries) { this._shaderParametersAssignDictionaries = dictionaries; } setShaderAssignDictionaries(dictionaries) { this._newShaderInstance = null; this._backupShaderClassDic = {}; this._shaderAssignDictionaries = []; for (let directory of dictionaries) { let meshes = []; for (let instance of directory.instances) { if (instance instanceof M_Group) { meshes = meshes.concat(instance.searchElementsByType(GLBoost.M_Mesh)); } else { meshes.push(instance); } } this._shaderAssignDictionaries.push({ instances: meshes, shaderClass: directory.shaderClass }); } } _assignWebGLStates() { if (this._webglStatesAssignDictionaries.length === 0) { return; } for (let dic of this._webglStatesAssignDictionaries) { for (let material of dic.materials) { this._backupWebGLStatesOfMaterials.push({ material: material, states: material.states }); material.states = dic.states; } } } _restoreWebGLStates() { if (this._backupWebGLStatesOfMaterials.length === 0) { return; } for (let dic of this._backupWebGLStatesOfMaterials) { dic.material.states = dic.states; } } _assignShaderParameters() { if (this._shaderParametersAssignDictionaries.length === 0) { return; } for (let dic of this._shaderParametersAssignDictionaries) { for (let mesh of this._meshes) { let materials = mesh.getAppropriateMaterials(); for (let material of materials) { this._backupShaderParametersOfMaterials.push({ mesh: mesh, shaderParameters: material.shaderParameters }); material.shaderParameters = dic.shaderParameters; } } } } _restoreShaderParameters() { if (this._backupShaderParametersOfMaterials.length === 0) { return; } /* for (let dic of this._backupShaderParametersOfMaterials) { let materials = dic.mesh.getAppropriateMaterials(); for (let i=0; i { this._backupShadersOfInstances.push({ instance: obj, backupShaderClass: material.shaderClass, backupShaderInstance: material.shaderInstance }); if (this._newShaderInstance && material.shaderClass.name !== this._oldShaderClass.name) { this._newShaderInstance.readyForDiscard(); this._newShaderInstance = void 0; // material.shaderInstance.readyForDiscard(); // material.shaderInstance = void 0; } if (!this._newShaderInstance) { // let materials = obj.geometry.prepareToRender(this.expression, existCamera_f, lights, null, obj, dic.shaderClass); // this._newShaderInstance = materials.filter((mat)=>{return mat.instanceName === material.instanceName})[0].shaderInstance; let glslProgram = obj.geometry.prepareGLSLProgramAndSetVertexNtoMaterial(this.expression, material, existCamera_f, lights, dic.shaderClass); this._oldShaderClass = material.shaderClass; this._newShaderInstance = material.shaderInstance; } // material.shaderInstance = this._newShaderInstance; }); } } } } _restoreShaders(existCamera_f, lights) { if (this._backupShadersOfInstances.length === 0) { return; } for (let dic of this._backupShadersOfInstances) { dic.instance.getAppropriateMaterials().forEach((material,index)=>{ // material.shaderClass = (dic.backupShaderClass); // material.shaderInstance = dic.backupShaderInstance; // if (typeof this._backupShaderClassDic[dic.backupShaderClass.name] === 'undefined') { let shaderInstance = dic.backupShaderInstance; if(!shaderInstance) { // let materials = obj.geometry.prepareToRender(this.expression, existCamera_f, lights, null, obj, dic.shaderClass); // shaderInstance = materials.filter((mat)=>{return mat.instanceName === material.instanceName})[0].shaderInstance; material.shaderInstance = obj.geometry.prepareGLSLProgramAndSetVertexNtoMaterial(this.expression, material, existCamera_f, lights, dic.shaderClass); } // material.shaderInstance = shaderInstance;// this._backupShaderClassDic[dic.backupShaderClass.name]; }); } } clearAssignShaders() { for (let dic of this._shaderAssignDictionaries) { if (dic._newShaderInstance) { dic._newShaderInstance.readyForDiscard(); } dic._newShaderInstance = void 0; } } /** * this function is called final part of prepareToRender */ set customFunctionWhenPrepareToRender(func) { this._customFunctionWhenPrepareToRender = func; } get customFunctionWhenPrepareToRender() { return this._customFunctionWhenPrepareToRender; } set customFunctionWhenPreRender(func) { this._customFunctionWhenPreRender = func; } get customFunctionWhenPreRender() { return this._customFunctionWhenPreRender; } set customFunctionWhenPostRender(func) { this._customFunctionWhenPostRender = func; } get customFunctionWhenPostRender() { return this._customFunctionWhenPostRender; } prepareToRender(expression) { let collectElements = function(elem, elementsType) { if (elem instanceof M_Group) { var children = elem.getChildren(); var meshes = []; children.forEach(function(child) { var childMeshes = collectElements(child, elementsType); meshes = meshes.concat(childMeshes); }); return meshes; } else if (elem instanceof elementsType) { return [elem]; } else { return []; } }; this._meshes = []; this._preGizmos = []; this._postGizmos = []; this._effekseerElements = []; if (this._scene) { // collect meshes this._meshes = collectElements(this._scene, M_Mesh); } // collect gizmos let collectGizmos = (elem)=> { if (elem instanceof M_Group) { var children = elem.getChildren(); children.forEach((child)=> { collectGizmos(child); }); } if (elem.gizmos) { elem.gizmos.filter((gizmo)=>{ if (gizmo.isPreDraw) { this._preGizmos.push(gizmo); } else { this._postGizmos.push(gizmo); } }); } }; if (this._scene != null) { collectGizmos(this._scene); } this._opacityMeshes = []; this._transparentMeshes = []; this._meshes.forEach((mesh)=>{ if (mesh.isTransparent) { this._transparentMeshes.push(mesh); } else { this._opacityMeshes.push(mesh); } }); this._skeletalMeshes = []; this._meshes.forEach((mesh)=>{ if (mesh.instanceName.indexOf('SkeletalMesh') !== -1) { this._skeletalMeshes.push(mesh); } }); if (this._scene) { this._effekseerElements = collectElements(this._scene, EffekseerElement$1); } if (this._scene) { this._scene.prepareToRender(expression); } // Setting RenderPass Specific Shader var camera = this.scene.getMainCamera(this); let lights = this.scene.lightsExceptAmbient; for (let dic of this._shaderAssignDictionaries) { for (let obj of dic.instances) { let renderSpecificMaterials = []; obj.getAppropriateMaterials().forEach((material, index) => { let newMaterial = this._glBoostSystem._glBoostContext.createClassicMaterial(); newMaterial._textureDic = Object.assign({}, material._textureDic); newMaterial._texturePurposeDic = material._texturePurposeDic.concat(); newMaterial._textureContributionRateDic = Object.assign({}, material._textureContributionRateDic); //newMaterial._originalMaterial = material; renderSpecificMaterials.push(newMaterial); }); let materials = obj.geometry.prepareToRender(this.expression, camera ? true : false, lights, null, obj, dic.shaderClass, renderSpecificMaterials); obj.getAppropriateMaterials().forEach((material, index) => { material['renderpassSpecificMaterial_' + this.instanceName + '_material_' + index] = materials[index]; }); } } if (this._customFunctionWhenPrepareToRender) { this._customFunctionWhenPrepareToRender(); } } sortTransparentMeshes(camera) { this._transparentMeshes.forEach((mesh)=> { mesh.calcTransformedDepth(camera); }); this._transparentMeshes.sort(function(a,b){ if( a.transformedDepth < b.transformedDepth ) return -1; if( a.transformedDepth > b.transformedDepth ) return 1; return 0; }); } set isEnableToDraw(flg) { this._isEnableToDraw = flg; } get isEnableToDraw() { return this._isEnableToDraw; } preRender(existCamera_f, lights) { if (!this.doPreRender) { return; } if (this._customFunctionWhenPreRender) { this._customFunctionWhenPreRender(); } this._assignWebGLStates(); // this._assignShaderParameters(); // this._assignShaders(existCamera_f, lights); // And call functions registered by user. } postRender(existCamera_f, lights) { if (!this.doPostRender) { return; } if (this._customFunctionWhenPostRender) { this._customFunctionWhenPostRender(); } // this._restoreShaders(existCamera_f, lights); this._restoreWebGLStates(); //this._restoreShaderParameters(); // And call functions registered by user. } set transparentMeshesAsManualOrder(meshes) { this._transparentMeshesAsManualOrder = meshes; } get transparentMeshesAsManualOrder() { return this._transparentMeshesAsManualOrder; } } // /** * This class take a role as operator of rendering process. In order to render images to canvas, this Renderer class gathers other elements' data, decides a plan of drawing process, and then just execute it. */ class Renderer extends GLBoostObject { constructor(glBoostContext, parameters) { super(glBoostContext); var _clearColor = parameters.clearColor; this._glBoostSystem._glBoostContext.reflectGlobalGLState(); const glContext = this._glContext; const gl = glContext.gl; if (_clearColor) { gl.clearColor( _clearColor.red, _clearColor.green, _clearColor.blue, _clearColor.alpha ); } this.__logger = Logger.getInstance(); this.__animationFrameId = -1; this.__isWebVRMode = false; this.__webvrFrameData = null; this.__webvrDisplay = null; this.__canvasWidthBackup = null; this.__canvasHeightBackup = null; this.__defaultUserSittingPositionInVR = new Vector3(0.0, 1.1, 1.5); this.__requestedToEnterWebVR = false; this.__isReadyForWebVR = false; this.__animationFrameObject = window; this.__effekseerElements = []; } /** * update things of elements of the expression. * @param expression a instance of Expression class */ update(expression ) { let skeletalMeshes = []; let effekseerElements = []; // gather scenes as unique for (let renderPass of expression.renderPasses) { skeletalMeshes = skeletalMeshes.concat(renderPass._skeletalMeshes); // effekseerElements = effekseerElements.concat(renderPass._effekseerElements); effekseerElements = effekseerElements.concat(renderPass.scene.searchElementsByType(EffekseerElement$1)); renderPass.scene.updateAmountOfAmbientLightsIntensity(); let camera = renderPass.scene.getMainCamera(); for (let effekseerElement of effekseerElements) { effekseerElement.update(camera); } } this.__effekseerElements = effekseerElements; let unique = function(array) { return array.reduce(function(a, b) { if (a.instanceName !== b.instanceName) { a.push(b); } return a; }, []); }; skeletalMeshes = unique(skeletalMeshes); for (let mesh of skeletalMeshes) { mesh.geometry.update(mesh); } if (typeof effekseer !== "undefined" && this.__effekseerElements.length > 0) { effekseer.update(); } } /** * draw elements of the expression. * @param expression a instance of Expression class */ draw(expression ) { let renderPassTag = ''; expression.renderPasses.forEach((renderPass, index)=>{ if (!renderPass.isEnableToDraw || !renderPass.scene) { return; } if (GLBoost.VALUE_CONSOLE_OUT_FOR_DEBUGGING && GLBoost.valueOfGLBoostConstants[GLBoost.LOG_TYPE_PERFORMANCE] !== false) { renderPass._startUnixTime = performance.now(); } if (renderPassTag !== renderPass.tag) { renderPass.clearAssignShaders(); } renderPassTag = renderPass.tag; var camera = renderPass.scene.getMainCamera(); let lights = renderPass.scene.lightsExceptAmbient; renderPass.preRender(camera ? true:false, lights); var glContext = this._glContext; var gl = glContext.gl; var glem = GLExtensionsManager.getInstance(this._glContext); // set render target buffers for each RenderPass. /* if (renderPass.fbo && renderPass.isRenderTargetAttachedTextures) { gl.bindTexture(gl.TEXTURE_2D, null); gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo); } else { glem.drawBuffers(gl, [gl.BACK]); } */ if (renderPass.fbo && renderPass.isRenderTargetAttachedTextures) { gl.bindFramebuffer(gl.FRAMEBUFFER, renderPass.fbo); } glem.drawBuffers(gl, renderPass.buffersToDraw); //glem.readBuffer(gl, renderPass.buffersToDraw); let viewport = null; if (renderPass.viewport) { viewport = [renderPass.viewport.x, renderPass.viewport.y, renderPass.viewport.z, renderPass.viewport.w]; } else { if (this.isWebVRMode) { viewport = [0, 0, glContext.canvasWidth, glContext.canvasHeight]; } else if (camera) { let deltaWidth = glContext.canvasHeight*camera.aspect - glContext.canvasWidth; viewport = [-deltaWidth/2, 0, glContext.canvasHeight*camera.aspect, glContext.canvasHeight]; } else { viewport = [0, 0, glContext.canvasWidth, glContext.canvasHeight]; } } if (!this.isWebVRMode) { gl.viewport.apply(gl, viewport); } this._clearBuffer(gl, renderPass); if (this.__animationFrameObject === this.__webvrDisplay) { this.__webvrDisplay.getFrameData(this.__webvrFrameData); if (this.__webvrDisplay.stageParameters) { this.__webvrFrameData.sittingToStandingTransform = this.__webvrDisplay.stageParameters.sittingToStandingTransform; } else { this.__webvrFrameData.sittingToStandingTransform = Matrix44$1.translate(this.__defaultUserSittingPositionInVR).flatten(); } } // draw pre gizmos this._drawGizmos(renderPass.preGizmos, expression, lights, camera, renderPass, index, viewport, true); // draw opacity meshes. const opacityMeshes = renderPass.opacityMeshes; opacityMeshes.forEach((mesh)=> { if (mesh.isVisible) { mesh.draw({ expression: expression, lights: lights, camera: camera, renderPass: renderPass, renderPassIndex: index, viewport: viewport, isWebVRMode: this.isWebVRMode, webvrFrameData: this.__webvrFrameData }); } }); if (camera) { renderPass.sortTransparentMeshes(camera); } // draw transparent meshes. const transparentMeshes = (renderPass.transparentMeshesAsManualOrder) ? renderPass.transparentMeshesAsManualOrder : renderPass.transparentMeshes; transparentMeshes.forEach((mesh)=> { //console.log(mesh.userFlavorName); if (mesh.isVisible && mesh.isTransparent) { mesh.draw({ expression: expression, lights: lights, camera: camera, renderPass: renderPass, renderPassIndex: index, viewport: viewport, isWebVRMode: this.isWebVRMode, webvrFrameData: this.__webvrFrameData }); } }); // draw post gizmos this._drawGizmos(renderPass.postGizmos, expression, lights, camera, renderPass, index, viewport, false); gl.bindFramebuffer(gl.FRAMEBUFFER, null); // glem.drawBuffers(gl, [gl.BACK]); if (typeof effekseer !== "undefined" && this.__effekseerElements.length > 0 && camera != null) { const projection = camera.projectionRHMatrix().m; const viewing = camera.lookAtRHMatrix().multiply(camera.inverseWorldMatrixWithoutMySelf).m; effekseer.setProjectionMatrix(projection); effekseer.setCameraMatrix(viewing); effekseer.draw(); } renderPass.postRender(camera ? true:false, lights); renderPass._endUnixTime = performance.now(); }); if (GLBoost.VALUE_CONSOLE_OUT_FOR_DEBUGGING && GLBoost.valueOfGLBoostConstants[GLBoost.LOG_TYPE_PERFORMANCE] !== false) { expression.renderPasses.forEach((renderPass, index)=>{ this.__logger.out(GLBoost.LOG_LEVEL_INFO, GLBoost.LOG_TYPE_PERFORMANCE, false, `RenderPass[${index}]: ${renderPass._endUnixTime - renderPass._startUnixTime}`); }); } } _drawGizmos(gizmos, expression, lights, camera, renderPass, index, viewport, isDepthTest) { const globalStatesUsageBackup = this._glBoostSystem._glBoostContext.globalStatesUsage; this._glBoostSystem._glBoostContext.globalStatesUsage = GLBoost.GLOBAL_STATES_USAGE_INCLUSIVE; this._glBoostSystem._glBoostContext.currentGlobalStates = [ 3042, // gl.BLEND ]; if (isDepthTest) { this._glBoostSystem._glBoostContext.currentGlobalStates.push(2929); // gl.DEPTH_TEST } for (let gizmo of gizmos) { if (gizmo.isVisible) { gizmo.mesh.draw({ expression: expression, lights: lights, camera: camera, renderPass: renderPass, renderPassIndex: index, viewport: viewport, isWebVRMode: this.isWebVRMode, webvrFrameData: this.__webvrFrameData, forceThisMaterial: gizmo.forceThisMaterial }); } } this._glBoostSystem._glBoostContext.globalStatesUsage = globalStatesUsageBackup; this._glBoostSystem._glBoostContext.restoreGlobalStatesToDefault(); } _clearBuffer(gl, renderPass) { const clearColor = renderPass.clearColor; const clearDepth = renderPass.clearDepth; const colorMask = renderPass.colorMask; if (clearColor) { gl.clearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w); } if (clearDepth) { gl.clearDepth(clearDepth); } if (colorMask) { gl.colorMask.apply(null, [colorMask]); } if (renderPass.buffersToDraw[0] === gl.NONE) { { gl.clear(gl.DEPTH_BUFFER_BIT); } } else if (clearColor || clearDepth) { gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); } else if (clearColor) { gl.clear( gl.COLOR_BUFFER_BIT ); } } /** * clear color/depth/stencil of canvas. * @param color_flg true: clear color, false: don't clear color * @param depth_flg true: clear depth, false: don't clear depth * @param stencil_flg true: clear stencil, false: don't clear stencil */ clearCanvas( color_flg , depth_flg , stencil_flg ) { const gl = this._glContext.gl; var bufferBits = 0; if ( color_flg === void 0 || color_flg ) bufferBits |= gl.COLOR_BUFFER_BIT; if ( depth_flg === void 0 || depth_flg ) bufferBits |= gl.DEPTH_BUFFER_BIT; if ( stencil_flg === void 0 || stencil_flg ) bufferBits |= gl.STENCIL_BUFFER_BIT; gl.clear( bufferBits ); } /** * Get WebGL context. * @returns a context of WebGL */ get glContext() { return this._glContext.gl; } /** * resize canvas and viewport. * @param width width to resize. * @param height height to resize. */ resize(width , height ) { this._glContext.canvasWidth = width; this._glContext.canvasHeight = height; } /** * This method treats the given callback function as a render loop and call it every frame. */ doRenderLoop(renderLoopFunc, time, ...args) { args.splice(0, 0, time); renderLoopFunc.apply(renderLoopFunc, args); this.__animationFrameId = this.__animationFrameObject.requestAnimationFrame((_time)=>{ this.doRenderLoop(renderLoopFunc, _time, args[1]); if (this.__requestedToEnterWebVR) { this.__isWebVRMode = true; } }, time); } doConvenientRenderLoop(expression, beforeCallback, afterCallback, ...args) { if (beforeCallback) { beforeCallback.apply(beforeCallback, args); } this.clearCanvas(); this.update(expression); this.draw(expression); if (afterCallback) { afterCallback.apply(afterCallback, args); } if (this.__webvrDisplay && this.__webvrDisplay.isPresenting) { this.__webvrDisplay.submitFrame(); } this.__animationFrameId = this.__animationFrameObject.requestAnimationFrame(()=>{ this.doConvenientRenderLoop(expression, beforeCallback, afterCallback, ...args); if (this.__requestedToEnterWebVR) { this.__isWebVRMode = true; } }); } stopRenderLoop() { this.__cancelAnimationFrame(this.__animationFrameId); this.__animationFrameId = -1; } // WebVR async enterWebVR(initialUserSittingPositionIfStageParametersDoNotExist, minRenderWidth = null, minRenderHeight = null) { if (initialUserSittingPositionIfStageParametersDoNotExist) { this.__defaultUserSittingPositionInVR = initialUserSittingPositionIfStageParametersDoNotExist; } this.__minRenderWidthFromUser = minRenderWidth; this.__minRenderHeightFromUser = minRenderHeight; return new Promise((resolve, reject)=> { if (!this.__webvrDisplay.isPresenting) { this.__animationFrameObject = this.__webvrDisplay; const leftEye = this.__webvrDisplay.getEyeParameters("left"); const rightEye = this.__webvrDisplay.getEyeParameters("right"); this.__canvasWidthBackup = this._glContext.canvasWidth; this.__canvasHeightBackup = this._glContext.canvaHeight; if (this.__minRenderWidthFromUser > leftEye.renderWidth && this.__minRenderHeightFromUser > rightEye.renderWidth) { this.resize(this.__minRenderWidthFromUser * 2, this.__minRenderHeightFromUser); } else { this.resize(Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2, Math.max(leftEye.renderHeight, rightEye.renderHeight)); } this.__webvrDisplay.requestPresent([{source: this._glContext.canvas}]).then(() => { //this.__switchAnimationFrameFunctions(this.__webvrDisplay); this.__requestedToEnterWebVR = true; resolve(); }).catch(() => { console.error('Failed to requestPresent. Please check your VR Setting, or something wrong with your VR system?'); reject(); }); } }); } async readyForWebVR(requestButtonDom) { if ( window.VRFrameData ) { this.__webvrFrameData = new window.VRFrameData(); } return new Promise((resolve, reject)=> { if ( navigator.getVRDisplays ) { navigator.getVRDisplays() .then((vrDisplays)=>{ if (vrDisplays.length > 0) { const webvrDisplay = vrDisplays[vrDisplays.length - 1]; webvrDisplay.depthNear = 0.01; webvrDisplay.depthFar = 10000; if (webvrDisplay.capabilities.canPresent) { this.__webvrDisplay = webvrDisplay; if (requestButtonDom) { requestButtonDom.style.display = 'block'; } else { const paragrach = document.createElement("p"); const anchor = document.createElement("a"); anchor.setAttribute("id", 'enter-vr'); const enterVr = document.createTextNode("Enter VR"); anchor.appendChild(enterVr); paragrach.appendChild(anchor); const canvas = this.glContext.canvas; canvas.parent.insertBefore(paragrach, canvas); window.addEventListener('click', this.enterWebVR.bind(this)); } this.__isReadyForWebVR = true; resolve(); } else { console.error("Can't requestPresent now. try again."); reject(); } } else { console.error('Failed to get VR Display. Please check your VR Setting, or something wrong with your VR system?'); reject(); } }) .catch(()=>{ console.error('Failed to get VR Displays. Please check your VR Setting.'); reject(); }); } else { console.error('Your browser does not support WebVR. Or it is disabled. Check again.'); reject(); } }); } async exitWebVR() { this.__isWebVRMode = false; if (this.__webvrDisplay && this.__webvrDisplay.isPresenting) { await this.__webvrDisplay.exitPresent(); } this.resize(this.__canvasWidthBackup, this.__canvasHeightBackup); this.__isReadyForWebVR = false; this.__animationFrameObject = window; } async disableWebVR() { this.__isWebVRMode = false; this.__requestedToEnterWebVR = false; this.__isReadyForWebVR = false; if (this.__webvrDisplay && this.__webvrDisplay.isPresenting) { await this.__webvrDisplay.exitPresent(); } this.__animationFrameObject = window; this.__webvrDisplay = null; } get isWebVRMode() { return this.__isWebVRMode; } get isReadyForWebVR() { return this.__isReadyForWebVR; } webVrSubmitFrame() { if (this.__webvrDisplay && this.__webvrDisplay.isPresenting) { this.__webvrDisplay.submitFrame(); } } } /* */ /** * This M_Scene class is the top level element of scene graph hierarchy. * To render scene, pass this scene element to Renderer.draw method. */ class M_Scene extends M_Group { /** * constructor * @param {HTMLCanvas|string} canvas canvas or canvas' id string. */ constructor(glBoostContext ) { super(glBoostContext); this._gl = this._glContext.gl; this._reset(); } _reset() { this._meshes = []; this._lights = []; this._lightsExceptAmbient = []; this._ambientLights = []; this._cameras = []; this._accumulatedAmbientIntensity = Vector4$1.zero(); } _getCurrentAnimationInputValue(inputName ) { let value = this._currentAnimationInputValues[inputName]; if (typeof value === 'undefined') { return (void 0); } else { return value; } } /** * Prepare for Rendering. You have to call this method before Renderer.draw method. */ prepareToRender(expression ) { this._reset(); var aabb = (function setParentAndClearAccumulatedTransformMatriAndMergeAABBRecursively(elem) { if (elem instanceof M_Group) { elem._needUpdate(); // This line enforces to clear AccumulatedTransformMatrix for all below elements. var children = elem.getChildren(); for(let i=0; i { this._lights = this._lights.concat(collectLights(elm)); this._lightsExceptAmbient = this._lights.filter((light)=>{return !light.isTypeAmbient();}); this._ambientLights = this._lights.filter((light)=>{return light.isTypeAmbient();}); }); let existCamera_f = false; let collectCameras = function(elem) { if (elem instanceof M_Group) { var children = elem.getChildren(); var cameras = []; children.forEach(function(child) { var childCameras = collectCameras(child); cameras = cameras.concat(childCameras); }); return cameras; } else if (elem instanceof M_AbstractCamera) { existCamera_f = true; return [elem]; } else { return []; } }; this._cameras = []; this._elements.forEach((elm)=> { this._cameras = this._cameras.concat(collectCameras(elm)); }); if (this._cameras.length === 0) ; else if (this._cameras.length === 1) { this._cameras[0].setAsMainCamera(this); } else { // If there are two or more cameras present in the scene and the main camera is not explicitly specified, // a camera chosen to be irresponsible is made the main camera. let isNotMainCameraFound = true; for (let camera of this._cameras) { if (camera.isMainCamera(this)) { isNotMainCameraFound = false; break; } } if (isNotMainCameraFound) { this._cameras[0].setAsMainCamera(this); // } } let collectMeshes = function(elem) { if (elem instanceof M_Group) { var children = elem.getChildren(); var meshes = []; children.forEach(function(child) { var childMeshes = collectMeshes(child); meshes = meshes.concat(childMeshes); }); return meshes; } else if (elem instanceof M_Mesh) { return [elem]; } else { return []; } }; this._meshes = []; this._elements.forEach((elm)=> { this._meshes = this._meshes.concat(collectMeshes(elm)); }); let callPrepareToRenderMethodOfAllElements = (elem)=> { if (elem instanceof M_Group) { var children = elem.getChildren(); children.forEach(function (child) { callPrepareToRenderMethodOfAllElements(child); }); for (let gizmo of elem.gizmos) { gizmo.mesh.prepareToRender(expression, existCamera_f, []); } } else if (elem instanceof M_Mesh) { elem.prepareToRender(expression, existCamera_f, this._lights); for (let gizmo of elem.gizmos) { gizmo.mesh.prepareToRender(expression, existCamera_f, this._lights); if (gizmo.forceThisMaterial) { gizmo.forceThisMaterial.shaderInstance = gizmo.mesh.geometry.prepareGLSLProgram(expression, gizmo.forceThisMaterial, existCamera_f, this._lights, null); } } } else if (elem instanceof M_Element) { elem.prepareToRender(); for (let gizmo of elem.gizmos) { gizmo.mesh.prepareToRender(expression, existCamera_f, []); } } else { return; } }; callPrepareToRenderMethodOfAllElements(this); } getMainCamera(renderPass ) { var camera = null; this.cameras.forEach((elm)=> { if (elm.isMainCamera(this)) { camera = elm; } }); return camera; } get lightsExceptAmbient() { return this._lightsExceptAmbient; } updateAmountOfAmbientLightsIntensity() { this._accumulatedAmbientIntensity = Vector4$1.zero(); for (let light of this._ambientLights) { this._accumulatedAmbientIntensity.add(light.intensity); } } getAmountOfAmbientLightsIntensity() { return this._accumulatedAmbientIntensity.clone(); } /** * Get child elements which belong to this scene. * @return child elements of this scene. */ getChildren() { return this._elements; } /** * Get child elements which belong to this scene. * @return child elements of this scene. */ get elements() { return this._elements; } /** * Get child meshes which belong to this scene. * @return child meshes of this scene. */ get meshes() { return this._meshes; } /** * Get child lights which belong to this scene. * @return child lights of this scene. */ get lights() { return this._lights; } get lightsExceptAmbient() { return this._lightsExceptAmbient; } /** * Get child cameras which belong to this scene. * @return child cameras of this scene. */ get cameras() { return this._cameras; } } class M_Gizmo extends M_Group { constructor(glBoostContext) { super(glBoostContext, null, null); this._mesh = null; // Whether or not to draw this gizmo before normal meshes drawing. // If true, draw this gizmo before normal meshes drawing. // If false, draw this gizmo after normal meshes drawing. this._isPreDraw = false; this._forceThisMaterial = null; } get mesh() { return this._mesh; } set isPreDraw(flg) { this._isPreDraw = flg; } get isPreDraw() { return this._isPreDraw; } get forceThisMaterial() { return this._forceThisMaterial; } } class JointPrimitive extends Geometry { constructor(glBoostContext, length, lineCount = 1) { super(glBoostContext); this._colors = []; this.color = new Vector4$1(1, 1, 1, 1); this._worldPositionOfThisJoint = new Vector3(0, 0, 1); this._worldPositionOfParentJoint = new Vector3(0, 0, 0); this._vertexData = this._setupVertexData(); this.setVerticesData(this._vertexData, null, GLBoost$1.LINES); this._width = 1; } _setupVertexData() { let length = Vector3.lengthBtw(this._worldPositionOfThisJoint, this._worldPositionOfParentJoint); let arrowWidth = this._width; let arrowheadLength = length/7.5; let arrowStickLength = length - arrowheadLength; let positions = []; let deltaVec = Vector3.subtract(this._worldPositionOfParentJoint, this._worldPositionOfThisJoint); let directionToParent = new Vector3(0, 1, 0); if (!deltaVec.isEqual(Vector3.zero())) { directionToParent = Vector3.subtract(this._worldPositionOfParentJoint, this._worldPositionOfThisJoint).normalize(); } const arrowStickPosition = Vector3.add(this._worldPositionOfThisJoint, Vector3.multiply(directionToParent, arrowStickLength)); let dummyVector = new Vector3(0, 1, 0); let dummyVector2 = new Vector3(0, -1, 0); if (Math.abs(Vector3.dotProduct(directionToParent, dummyVector)) > 0.4) { dummyVector = new Vector3(1, 0, 0); dummyVector2 = new Vector3(-1, 0, 0); } if (Math.abs(Vector3.dotProduct(directionToParent, dummyVector)) > 0.4) { dummyVector = new Vector3(0, 0, 1); dummyVector2 = new Vector3(0, 0, -1); } const crossVector = Vector3.multiply(Vector3.cross(directionToParent, dummyVector).normalize(), arrowWidth); const crossVector2 = Vector3.multiply(Vector3.cross(directionToParent, crossVector).normalize(), arrowWidth); const crossVector3 = Vector3.multiply(Vector3.cross(directionToParent, dummyVector2).normalize(), arrowWidth); const crossVector4 = Vector3.multiply(Vector3.cross(directionToParent, crossVector3).normalize(), arrowWidth); //const crossVector = Matrix44.rotate(directionToParent) const crossPosition = Vector3.add(arrowStickPosition, crossVector); const crossPosition2 = Vector3.add(arrowStickPosition, crossVector2); const crossPosition3 = Vector3.add(arrowStickPosition, crossVector3); const crossPosition4 = Vector3.add(arrowStickPosition, crossVector4); // Long Pyramid positions.push(this._worldPositionOfThisJoint); positions.push(crossPosition); positions.push(this._worldPositionOfThisJoint); positions.push(crossPosition2); positions.push(this._worldPositionOfThisJoint); positions.push(crossPosition3); positions.push(this._worldPositionOfThisJoint); positions.push(crossPosition4); // Plane positions.push(crossPosition); positions.push(crossPosition2); positions.push(crossPosition2); positions.push(crossPosition3); positions.push(crossPosition3); positions.push(crossPosition4); positions.push(crossPosition4); positions.push(crossPosition); // Short Pyramid positions.push(this._worldPositionOfParentJoint); positions.push(crossPosition); positions.push(this._worldPositionOfParentJoint); positions.push(crossPosition2); positions.push(this._worldPositionOfParentJoint); positions.push(crossPosition3); positions.push(this._worldPositionOfParentJoint); positions.push(crossPosition4); this._vertexData = { position: positions, color: this._colors }; return this._vertexData; } set worldPositionOfThisJoint(vec) { this._worldPositionOfThisJoint = vec; } get worldPositionOfThisJoint() { return this._worldPositionOfThisJoint; } set worldPositionOfParentJoint(vec) { this._worldPositionOfParentJoint = vec; } get worldPositionOfParentJoint() { return this._worldPositionOfParentJoint; } set width(value) { this._width = value; } get width() { return this._width; } set color(vec) { this._color = vec; this._colors = []; for(let i=0; i<24; i++) { this._colors.push(this._color); } } get color() { return this._color; } update() { this._vertexData = this._setupVertexData(); this.updateVerticesData(this._vertexData, true); } set meshContainingSelf(jointGizmoMesh) { this._mesh = jointGizmoMesh; } } GLBoost$1["JointPrimitive"] = JointPrimitive; class M_JointGizmo extends M_Gizmo { constructor(glBoostContext, joint, length) { super(glBoostContext, null, null); this._init(glBoostContext, joint, length); this.isVisible = false; this.baseColor = new Vector4$1(0.0, 1.0, 1.0, 0.25); } _init(glBoostContext, joint, length) { this._joint = joint; this._primitive = new JointPrimitive(this._glBoostContext, length, 1); this._mesh = new M_Mesh(glBoostContext, this._primitive, null ); this._mesh.masterElement = this; // this._mesh.rotate = new Vector3(-Math.PI/2, 0, 0); this.addChild(this._mesh); } set baseColor(colorVec) { this._primitive.color = colorVec; } get baseColor() { return this._primitive.color; } // Use master element's worldMatrix. get worldMatrixInner() { return Matrix44$1.identity(); } set worldPositionOfThisJoint(vec3) { this._primitive.worldPositionOfThisJoint = vec3; } get worldPositionOfThisJoint() { return this._primitive.worldPositionOfThisJoint; } set worldPositionOfParentJoint(vec3) { this._primitive.worldPositionOfParentJoint = vec3; } get worldPositionOfParentJoint() { return this._primitive.worldPositionOfParentJoint; } set width(value) { this._primitive.width = value; } get width() { return this._primitive.width; } update() { this._primitive.update(); } set isVisible(flag) { this._mesh.isVisible = flag; } get isVisible() { return this._mesh.isVisible; } } GLBoost$1['M_JointGizmo'] = M_JointGizmo; class M_Joint extends M_Element { constructor(glBoostContext, isExistJointGizmo = false) { super(glBoostContext); if (isExistJointGizmo) { this._gizmo = new M_JointGizmo(glBoostContext, this, length); this._gizmos.push(this._gizmo); } else { this._gizmo = {}; } M_Joint._calculatedTransforms = {}; M_Joint._calculatedTranslates = {}; this._childJoints = []; this._jointsOfParentHierarchies = []; this.length = new Vector3(length, length, length); this._isCalculatedJointGizmo = false; this._jointPoseMatrix = Matrix44$1.identity(); this._length = 1; this._inverseBindMatrix = Matrix44$1.identity(); this._skeletalMesh = null; } set inverseBindMatrix(mat4) { this._inverseBindMatrix = mat4; } get inverseBindMatrix() { return this._inverseBindMatrix; } set skeletalMesh(skeletalMesh) { this._skeletalMesh = skeletalMesh; } get skeletalMesh() { return this._skeletalMesh; } set worldPositionOfThisJoint(vec) { this._gizmo.worldPositionOfThisJoint = vec; } get worldPositionOfThisJoint() { return this._gizmo.worldPositionOfThisJoint; } set worldPositionOfParentJoint(vec) { this._gizmo.worldPositionOfParentJoint = vec; } get worldPositionOfParentJoint() { return this._gizmo.worldPositionOfParentJoint; } set width(value) { this._gizmo.width = value; } get width() { return this._gizmo.width; } set jointPoseMatrix(matrix) { this._jointPoseMatrix = matrix; } get jointPoseMatrix() { return this._jointPoseMatrix; } clearIsCalculatedLengthFlag() { this._isCalculatedJointGizmo = false; } get isCalculatedJointGizmo() { return this._isCalculatedJointGizmo; } set isVisible(flg) { this._gizmo.isVisible = flg; } get isVisible() { return this._gizmo.isVisible; } set childJoints(joints) { this._childJoints = joints; } get childJoints() { return this._childJoints; } set jointsOfParentHierarchies(joints) { this._jointsOfParentHierarchies = joints; } get jointsOfParentHierarchies() { return this._jointsOfParentHierarchies; } updateGizmoDisplay() { if (this._gizmo instanceof M_JointGizmo) { this._gizmo.update(); } } clone() { let instance = new M_Joint(this._glBoostSystem); this._copy(instance); return instance; } _copy(instance) { super._copy(instance); } } GLBoost$1['M_Joint'] = M_Joint; class M_SkeletalMesh extends M_Mesh { constructor(glBoostContext, geometry, material, rootJointName) { super(glBoostContext, geometry, material, rootJointName); this._rootJointName = rootJointName; this._jointsHierarchy = null; this._inverseBindMatrices = []; this._bindShapeMatrix = Matrix44$1.identity(); this._jointNames = []; // for glTF1.0 this._gltfJointIndices = []; // for glTF2.0 this._joints = []; // these are calculated by M_SkeletalGeometry this._jointMatrices = null; this._qArray = null; this._tArray = null; this._qtArray = null; this._translationScale = 0; } prepareToRender(expression, existCamera_f, lights, renderPasses) { let joints = this.jointsHierarchy.searchElementsByType(M_Joint); this._joints = []; // sort & choice joints according to jointNames for skinning /// for glTF1.0 let jointCount=0; for (let i=0; i { let children = joint.parent.parent.getChildren(); let parentJoint = null; for (let i=0; i 0) { const rootJointMatrix = this._joints[0].worldMatrix; let rootJointPosWorld = new Vector3(rootJointMatrix.multiplyVector(Vector4$1.zero())); return rootJointPosWorld; } return Vector3.zero(); } getRootJointsWorldPositionAt(inputValue) { if (this._joints.length > 0) { const rootJointMatrix = this._joints[0].getWorldMatrixAt(inputValue); let rootJointPosWorld = new Vector3(rootJointMatrix.multiplyVector(Vector4$1.zero())); return rootJointPosWorld; } return Vector3.zero(); } /* get rootJointsWorldPositionAsBindPose() { if (this._joints.length > 0) { const rootJointMatrix = this._joints[0].worldMatrixAsForJointsBindPose; let rootJointPosWorld = rootJointMatrix.multiplyVector(Vector4.zero()).toVector3(); return rootJointPosWorld; } return Vector3.zero(); } */ } GLBoost$1['M_SkeletalMesh'] = M_SkeletalMesh; class M_SkeletalGeometry extends Geometry { constructor(glBoostContext) { super(glBoostContext); this._skeletalShaderSpecified = null; this._skeletalShaderNormal = null; } update(skeletalMesh) { var joints = skeletalMesh._joints; var matrices = []; let areThereAnyJointsWhichHaveAnimation = false; if (joints[0].parent._getCurrentAnimationInputValue(joints[0].parent._activeAnimationLineName) !== null) { areThereAnyJointsWhichHaveAnimation = true; } let input = joints[0]._getCurrentAnimationInputValue('time'); let jointZeroWorldMatrix = null; let skeletalMeshWorldMatrix = null; let skeletalMeshTransformMatrixAccmulatedAncestry = skeletalMesh.getWorldMatrixAt(input); let inverseSkeletalMeshTransformMatrixAccmulatedAncestry = Matrix44$1.invert(skeletalMeshTransformMatrixAccmulatedAncestry); for (let i=joints.length-1; i>=0; i--) { let globalJointTransform = null; let inverseBindMatrix = joints[i].inverseBindMatrix; if (areThereAnyJointsWhichHaveAnimation) { globalJointTransform = joints[i].getWorldMatrixAt(input); skeletalMeshWorldMatrix = globalJointTransform; } else { globalJointTransform = skeletalMeshTransformMatrixAccmulatedAncestry; skeletalMeshWorldMatrix = globalJointTransform; let bindMat = joints[i].bindMatrix; globalJointTransform = Matrix44$1.multiply(skeletalMeshWorldMatrix, bindMat); } if (i === 0) { jointZeroWorldMatrix = globalJointTransform; } // if (true) { if (this._materialForSkeletals[0].shaderInstance && this._materialForSkeletals[0].shaderInstance.constructor === FreeShader) { matrices[i] = inverseSkeletalMeshTransformMatrixAccmulatedAncestry; } else { matrices[i] = Matrix44$1.identity(); } matrices[i] = Matrix44$1.multiply(matrices[i], globalJointTransform); joints[i].jointPoseMatrix = Matrix44$1.multiply(Matrix44$1.identity(), globalJointTransform); matrices[i] = Matrix44$1.multiply(matrices[i], inverseBindMatrix); matrices[i] = Matrix44$1.multiply(matrices[i], skeletalMesh.bindShapeMatrix); } GLBoost$1.JointGizmoUpdater.update(joints, jointZeroWorldMatrix); /* let s = matrices[i].getScale(); matrices[i].m00 /= s.x; matrices[i].m01 /= s.x; matrices[i].m02 /= s.x; matrices[i].m10 /= s.y; matrices[i].m11 /= s.y; matrices[i].m12 /= s.y; matrices[i].m20 /= s.z; matrices[i].m21 /= s.z; matrices[i].m22 /= s.z; let q = (Quaternion.fromMatrix(matrices[i])); q.normalize(); let t = matrices[i].getTranslate(); let matrix = new Matrix44(q); matrix.m00 *= s.x; matrix.m01 *= s.x; matrix.m02 *= s.x; matrix.m10 *= s.y; matrix.m11 *= s.y; matrix.m12 *= s.y; matrix.m20 *= s.z; matrix.m21 *= s.z; matrix.m22 *= s.z; matrix.putTranslate(t); matrices[i] = matrix; } */ if (!GLBoost$1.VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL) { let flatMatrices = []; for (let i=0; i 1) { /* { // comporess quaternion only skeletalMesh._qArray = new Float32Array(matrices.length * 2); skeletalMesh._tArray = new Float32Array(matrices.length * 3); for (let i=0; i 0) { var materials = this._materials; } else if (skeletalMesh.material){ var materials = [skeletalMesh.material]; } else { var materials = []; } */ // for (let i=0; i 1) { // `OneVec4` Vertion [Begin] Shader.trySettingVec4ArrayToUniform(gl, glslProgram, material, material._semanticsDic, 'JOINT_QUATTRANSLATION', skeletalMesh._qtArray); // this._glContext.uniform3f(material.getUniform(glslProgram, 'uniform_translationScale'), skeletalMesh._translationScale.x, skeletalMesh._translationScale.y, skeletalMesh._translationScale.z, true); // `OneVec4` Vertion [End] } // } //super.draw(expression, lights, camera, skeletalMesh, scene, renderPass_index); } prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh, shaderClassSpecified = void 0, argMaterials = void 0) { if (argMaterials !== void 0) { this._materialForSkeletals = argMaterials; } else { if (this._materials.length > 0) { this._materialForSkeletals = this._materials; } else if (meshMaterial) { this._materialForSkeletals = [meshMaterial]; } else { this._materialForSkeletals = [this._defaultMaterial]; } } let derrivedClass = null; if (!(this._materialForSkeletals[0].shaderInstance && this._materialForSkeletals[0].shaderInstance.constructor === FreeShader)) { let baseClass = null; if (shaderClassSpecified) { baseClass = shaderClassSpecified; class SkeletalShader extends baseClass { constructor(glBoostContext, basicShader) { super(glBoostContext, basicShader); SkeletalShader.mixin(SkeletalShaderSource); } } derrivedClass = SkeletalShader; this._skeletalShaderSpecified = derrivedClass; } else { for (let materialForSkeletal of this._materialForSkeletals) { baseClass = materialForSkeletal.shaderClass; class SkeletalShader extends baseClass { constructor(glBoostContext, basicShader) { super(glBoostContext, basicShader); SkeletalShader.mixin(SkeletalShaderSource); } } derrivedClass = SkeletalShader; } this._skeletalShaderNormal = derrivedClass; } for (let i = 0; i < this._materialForSkeletals.length; i++) { if (shaderClassSpecified) ; else { if (this._materialForSkeletals[i].shaderClass.name !== derrivedClass.name) { this._materialForSkeletals[i].shaderClass = derrivedClass; } } } } return super.prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh, derrivedClass, argMaterials); } } class M_OrthoCamera extends M_AbstractCamera { constructor(glBoostContext, toRegister, lookat, ortho) { super(glBoostContext, toRegister); this._lowLevelCamera = new L_OrthoCamera(this, false, lookat, ortho); this._lowLevelCamera._middleLevelCamera = this; } // ===================== delegate to low level class ======================== _needUpdateProjection() { this._lowLevelCamera._needUpdateProjection(); } get updateCountAsCameraProjection() { return this._lowLevelCamera.updateCountAsCameraProjection; } projectionRHMatrix() { return this._lowLevelCamera.projectionRHMatrix(); } set left(value) { this._lowLevelCamera.left = value; } get left() { return this._lowLevelCamera.left; } set right(value) { this._lowLevelCamera.right = value; } get right() { return this._lowLevelCamera.right; } set bottom(value) { this._lowLevelCamera.bottom = value; } get bottom() { return this._lowLevelCamera.bottom; } set top(value) { this._lowLevelCamera.top = value; } get top() { return this._lowLevelCamera.top; } set zNear(value) { this._lowLevelCamera.zNear = value; } get zNear() { return this._lowLevelCamera.zNear; } set zFar(value) { this._lowLevelCamera.zFar = value; } get zFar() { return this._lowLevelCamera.zFar; } set xmag(value) { this._lowLevelCamera.xmag = value; } get xmag() { return this._lowLevelCamera.xmag; } set ymag(value) { this._lowLevelCamera.ymag = value; } get ymag() { return this._lowLevelCamera.ymag; } get aspect() { return (this._lowLevelCamera.right - this._lowLevelCamera.left) / (this._lowLevelCamera.top - this._lowLevelCamera.bottom); } } GLBoost$1['M_OrthoCamera'] = M_OrthoCamera; /* */ class Arrow extends Geometry { constructor(glBoostSystem , length , lineCount = 1) { super(glBoostSystem); this._setupVertexData(length, lineCount); } _setupVertexData(length, lineCount) { let arrowheadWidth = length/10; let arrowheadLength = length/7.5; let stickLength = length - arrowheadLength; let halfLength = length/2; let positions = []; for (let i=0; i{return !light.isTypeAmbient();}).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_PhongShaderSource(f, gl, lights) { var shaderText = ''; shaderText += ' float depthBias = 0.005;\n'; shaderText += ' vec4 surfaceColor = rt0;\n'; shaderText += ' rt0 = vec4(0.0, 0.0, 0.0, 0.0);\n'; for (let i=0; i{ let gotText = responseText; let partsOfPath = url.split('/'); let basePath = ''; for(let i=0; i{ }); } _loadMaterialsFromString(glBoostContext, mtlString, defaultShader, basePath = '', resolve) { var mtlTextRows = mtlString.split('\n'); var numMaterial = 0; // checking the number of material for (let i=0; i{ resolve(materials); }); } _loadMaterialsFromFile(glBoostContext, basePath, fileName, defaultShader) { return DataUtil.loadResourceAsync(basePath + fileName, false, (resolve, responseText)=>{ this._loadMaterialsFromString(glBoostContext, responseText, defaultShader, basePath, resolve); }, (reject, err)=>{} ); } _constructMesh(glBoostContext, objText, basePath, defaultShader, mtlString, resolve) { //console.log(basePath); var objTextRows = objText.split('\n'); var promise = null; let vCount = 0; let fCount = 0; let vnCount = 0; let vtCount = 0; if (mtlString) { promise = (()=>{ return new Promise((resolve, reject)=> { this._loadMaterialsFromString(glBoostContext, mtlString, defaultShader, '', resolve); }); })(); } for (let i=0; i{ for (let i=0; i { if (isFinite(glboostConstant_or_glboostConstantValueName)) { let glboostConstant = glboostConstant_or_glboostConstantValueName; let glboostConstantName = GLBoost$1.getNameOfGLBoostConstant(glboostConstant); if (glboostConstantName) { let glboostConstantValueName = 'VALUE_' + glboostConstantName; Object.defineProperty(GLBoost$1, glboostConstantValueName, { get: function () { return this.valueOfGLBoostConstants[glboostConstant]; }, set: function (flg) { this.valueOfGLBoostConstants[glboostConstant] = flg; }, }); GLBoost$1[glboostConstantValueName] = value; } } else { let glboostConstantValueName = glboostConstant_or_glboostConstantValueName; GLBoost$1[glboostConstantValueName] = value; } }; /// define value of GLBoost global settings. let define = defineValueOfGLBoostConstants; define('VALUE_TARGET_WEBGL_VERSION', 1); define('VALUE_SKELETAL_SHADER_OPITIMIZATION_LEVEL', 0); define('VALUE_DEFAULT_POINTLIGHT_INTENSITY', new Vector3(1, 1, 1)); define('VALUE_ANGLE_UNIT', GLBoost$1.DEGREE); define('VALUE_WEBGL_ONE_USE_EXTENSIONS', true); define('VALUE_CONSOLE_OUT_FOR_DEBUGGING', false); define(GLBoost$1.LOG_GENERAL, true); define(GLBoost$1.LOG_SHADER_CODE, true); define(GLBoost$1.LOG_GLBOOST_OBJECT_LIFECYCLE, true); define(GLBoost$1.LOG_GL_RESOURCE_LIFECYCLE, true); define(GLBoost$1.LOG_TYPE_GL, false); define(GLBoost$1.LOG_OMISSION_PROCESSING, false); })(); class LambertShaderSource { FSDefine_LambertShaderSource(in_, f, lights) { var sampler2D = this._sampler2DShadow_func(); var shaderText = ''; shaderText += 'uniform vec4 Kd;\n'; shaderText += 'uniform vec4 ambient;\n'; // Ka * amount of ambient lights let lightNumExceptAmbient = lights.filter((light)=>{return !light.isTypeAmbient();}).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_LambertShaderSource(f, gl, lights) { var shaderText = ''; shaderText += ' vec4 surfaceColor = rt0;\n'; shaderText += ' rt0 = vec4(0.0, 0.0, 0.0, 0.0);\n'; for (let i=0; i * @return The singleton instance of GLTFLoader class */ static getInstance() { if (!this[singleton$6]) { this[singleton$6] = new GLTFLoader(singletonEnforcer$3); } return this[singleton$6]; } getDefaultShader(options) { let defaultShader = null; if (options && typeof options.defaultShaderClass !== "undefined") { if (typeof options.defaultShaderClass === "string") { defaultShader = GLBoost$1[options.defaultShaderClass]; } else { defaultShader = options.defaultShaderClass; } } return defaultShader; } getOptions(defaultOptions, json, options) { if (json.asset && json.asset.extras && json.asset.extras.loadOptions) { for (let optionName in json.asset.extras.loadOptions) { defaultOptions[optionName] = json.asset.extras.loadOptions[optionName]; } } for (let optionName in options) { defaultOptions[optionName] = options[optionName]; } if (defaultOptions.loaderExtension && typeof defaultOptions.loaderExtension === "string") { defaultOptions.loaderExtension = GLBoost$1[options.loaderExtension].getInstance(); } if (defaultOptions.statesOfElements) { for (let state of defaultOptions.statesOfElements) { if (state.shaderClass && typeof state.shaderClass === "string") { state.shaderClass = GLBoost$1[state.shaderClass]; } } } if (options && typeof options.defaultMaterial !== "undefined") { if (typeof options.defaultMaterial === "string") { defaultOptions.defaultMaterial = GLBoost$1[options.defaultMaterial]; } else { defaultOptions.defaultMaterial = options.defaultMaterial; } } if (defaultOptions.defaultMaterial != null && defaultOptions.defaultMaterial.name.indexOf('PBR') !== -1) { defaultOptions.defaultShaderClass = defaultOptions.defaultMaterial.shaderClass; } else if (options && typeof options.defaultShaderClass !== "undefined") { if (typeof options.defaultShaderClass === "string") { defaultOptions.defaultShaderClass = GLBoost$1[options.defaultShaderClass]; } else { defaultOptions.defaultShaderClass = options.defaultShaderClass; } } return defaultOptions; } /** * the method to load glTF file. * @param glBoostContext - glBoostContext instance * @param url - url of glTF file * @param options - option data for loading * @return a promise object */ loadGLTF(glBoostContext , url , options ) { let defaultOptions = { files: { // "foo.gltf": content of file as ArrayBuffer, // "foo.bin": content of file as ArrayBuffer, // "boo.png": content of file as ArrayBuffer }, loaderExtension: null, isNeededToMultiplyAlphaToColorOfPixelOutput: true, isTextureImageToLoadPreMultipliedAlphaAsDefault: false, isExistJointGizmo: false, isBlend: false, isDepthTest: true, defaultMaterial: ClassicMaterial$1, defaultShaderClass: null, isMeshTransparentAsDefault: false, ignoreMeshList: [], defaultStates: { states: { enable: [ // 3042, // BLEND ], functions: { //"blendFuncSeparate": [1, 0, 1, 0], } }, isTransparent: true, opacity: 1.0, shaderClass: DecalShader, // LambertShader // PhongShader isTextureImageToLoadPreMultipliedAlpha: false, globalStatesUsage: GLBoost$1.GLOBAL_STATES_USAGE_IGNORE // GLBoost.GLOBAL_STATES_USAGE_DO_NOTHING // GLBoost.GLOBAL_STATES_USAGE_INCLUSIVE // GLBoost.GLOBAL_STATES_USAGE_EXCLUSIVE }, statesOfElements: [ { targets: [], //["name_foo", "name_boo"], specifyMethod: GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME, // GLBoost.QUERY_TYPE_INSTANCE_NAME // GLBoost.QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR states: { enable: [ // 3042, // BLEND ], functions: { //"blendFuncSeparate": [1, 0, 1, 0], } }, isTransparent: true, opacity: 1.0, shaderClass: DecalShader, // LambertShader // PhongShader isTextureImageToLoadPreMultipliedAlpha: false, globalStatesUsage: GLBoost$1.GLOBAL_STATES_USAGE_IGNORE // GLBoost.GLOBAL_STATES_USAGE_DO_NOTHING // GLBoost.GLOBAL_STATES_USAGE_INCLUSIVE // GLBoost.GLOBAL_STATES_USAGE_EXCLUSIVE } ] }; this._materials = []; if (options && options.files) { for (let fileName in options.files) { const splitted = fileName.split('.'); const fileExtension = splitted[splitted.length - 1]; if (fileExtension === 'gltf' || fileExtension === 'glb') { return new Promise((resolve, response)=>{ this.checkArrayBufferOfGltf(options.files[fileName], null, options, defaultOptions, glBoostContext, resolve); }, (reject, error)=>{ }); } } } return DataUtil.loadResourceAsync(url, true, (resolve, response)=>{ var arrayBuffer = response; this.checkArrayBufferOfGltf(arrayBuffer, url, options, defaultOptions, glBoostContext, resolve); }, (reject, error)=>{ } ); } checkArrayBufferOfGltf(arrayBuffer, url, options, defaultOptions, glBoostContext, resolve) { let dataView = new DataView(arrayBuffer, 0, 20); let isLittleEndian = true; // Magic field let magicStr = ''; magicStr += String.fromCharCode(dataView.getUint8(0, isLittleEndian)); magicStr += String.fromCharCode(dataView.getUint8(1, isLittleEndian)); magicStr += String.fromCharCode(dataView.getUint8(2, isLittleEndian)); magicStr += String.fromCharCode(dataView.getUint8(3, isLittleEndian)); if (magicStr !== 'glTF') { this.loadAsTextJson(arrayBuffer, url, options, defaultOptions, glBoostContext, resolve); } else { this.loadAsBinaryJson(dataView, isLittleEndian, arrayBuffer, options, defaultOptions, glBoostContext, resolve); } } loadAsBinaryJson(dataView, isLittleEndian, arrayBuffer, options, defaultOptions, glBoostContext, resolve) { let gltfVer = dataView.getUint32(4, isLittleEndian); if (gltfVer !== 1) { reject('invalid version field in this binary glTF file.'); } let lengthOfThisFile = dataView.getUint32(8, isLittleEndian); let lengthOfContent = dataView.getUint32(12, isLittleEndian); let contentFormat = dataView.getUint32(16, isLittleEndian); if (contentFormat !== 0) { // 0 means JSON format reject('invalid contentFormat field in this binary glTF file.'); } let arrayBufferContent = arrayBuffer.slice(20, lengthOfContent + 20); let gotText = DataUtil.arrayBufferToString(arrayBufferContent); let json = JSON.parse(gotText); let arrayBufferBinary = arrayBuffer.slice(20 + lengthOfContent); let glTFVer = this._checkGLTFVersion(json); options = this.getOptions(defaultOptions, json, options); const defaultShader = options.defaultShaderClass; this._loadResourcesAndScene(glBoostContext, arrayBufferBinary, null, json, defaultShader, glTFVer, resolve, options); return { options, defaultShader }; } loadAsTextJson(arrayBuffer, url, options, defaultOptions, glBoostContext, resolve) { let gotText = DataUtil.arrayBufferToString(arrayBuffer); let basePath = ''; if (url) { let partsOfPath = url.split('/'); for (let i = 0; i < partsOfPath.length - 1; i++) { basePath += partsOfPath[i] + '/'; } } else { basePath = null; } let json = JSON.parse(gotText); let glTFVer = this._checkGLTFVersion(json); options = this.getOptions(defaultOptions, json, options); const defaultShader = options.defaultShaderClass; this._loadResourcesAndScene(glBoostContext, null, basePath, json, defaultShader, glTFVer, resolve, options); return { options, defaultShader }; } _checkGLTFVersion(json) { let glTFVer = 1.0; if (json.asset && json.asset.version) { glTFVer = parseFloat(json.asset.version); } return glTFVer; } _loadResourcesAndScene(glBoostContext, arrayBufferBinary, basePath, json, defaultShader, glTFVer, resolve, options) { let shadersJson = json.shaders; let shaders = {}; let buffers = {}; let textures = {}; let promisesToLoadResources = []; // Shaders Async load for (let shaderName in shadersJson) { shaders[shaderName] = {}; let shaderJson = shadersJson[shaderName]; let shaderType = shaderJson.type; if (typeof shaderJson.extensions !== 'undefined' && typeof shaderJson.extensions.KHR_binary_glTF !== 'undefined') { shaders[shaderName].shaderText = this._accessBinaryAsShader(shaderJson.extensions.KHR_binary_glTF.bufferView, json, arrayBufferBinary); shaders[shaderName].shaderType = shaderType; continue; } let shaderUri = shaderJson.uri; if (options.files) { const splitted = shaderUri.split('/'); const filename = splitted[splitted.length - 1]; if (options.files[filename]) { const arrayBuffer = options.files[filename]; shaders[shaderName].shaderText = DataUtil.arrayBufferToString(arrayBuffer); shaders[shaderName].shaderType = shaderType; continue; } } if (shaderUri.match(/^data:/)) { promisesToLoadResources.push( new Promise((fulfilled, rejected) => { let arrayBuffer = DataUtil.base64ToArrayBuffer(shaderUri); shaders[shaderName].shaderText = DataUtil.arrayBufferToString(arrayBuffer); shaders[shaderName].shaderType = shaderType; fulfilled(); }) ); } else { shaderUri = basePath + shaderUri; promisesToLoadResources.push( DataUtil.loadResourceAsync(shaderUri, false, (resolve, response)=>{ shaders[shaderName].shaderText = response; shaders[shaderName].shaderType = shaderType; resolve(); }, (reject, error)=>{ } ) ); } } // Buffers Async load for (let bufferName in json.buffers) { let bufferInfo = json.buffers[bufferName]; const splitted = bufferInfo.uri.split('/'); const filename = splitted[splitted.length - 1]; if (bufferInfo.uri.match(/^data:application\/(.*);base64,/)) { promisesToLoadResources.push( new Promise((fulfilled, rejected) => { let arrayBuffer = DataUtil.base64ToArrayBuffer(bufferInfo.uri); buffers[bufferName] = arrayBuffer; fulfilled(); }) ); } else if (bufferInfo.uri === '' || bufferInfo.uri === 'data:,') { buffers[bufferName] = arrayBufferBinary; } else if (options.files && options.files[filename]) { const arrayBuffer = options.files[filename]; buffers[bufferName] = arrayBuffer; } else { promisesToLoadResources.push( DataUtil.loadResourceAsync(basePath + bufferInfo.uri, true, (resolve, response)=>{ buffers[bufferName] = response; resolve(); }, (reject, error)=>{ } ) ); } } // Textures Async load for (let textureName in json.textures) { let textureJson = json.textures[textureName]; let imageJson = json.images[textureJson.source]; let samplerJson = json.samplers[textureJson.sampler]; let textureUri = null; if (typeof imageJson.extensions !== 'undefined' && typeof imageJson.extensions.KHR_binary_glTF !== 'undefined') { textureUri = this._accessBinaryAsImage(imageJson.extensions.KHR_binary_glTF.bufferView, json, arrayBufferBinary, imageJson.extensions.KHR_binary_glTF.mimeType); } else { let imageFileStr = imageJson.uri; const splitted = imageFileStr.split('/'); const filename = splitted[splitted.length - 1]; if (options.files && options.files[filename]) { const arrayBuffer = options.files[filename]; const splitted = filename.split('.'); const fileExtension = splitted[splitted.length - 1]; textureUri = this._accessArrayBufferAsImage(arrayBuffer, fileExtension); } else if (imageFileStr.match(/^data:/)) { textureUri = imageFileStr; } else { textureUri = basePath + imageFileStr; } } let texture = glBoostContext.createTexture(null, textureName, { 'TEXTURE_MAG_FILTER': samplerJson.magFilter, 'TEXTURE_MIN_FILTER': samplerJson.minFilter, 'TEXTURE_WRAP_S': samplerJson.wrapS, 'TEXTURE_WRAP_T': samplerJson.wrapT }); if (options.loaderExtension && options.loaderExtension.setUVTransformToTexture) { options.loaderExtension.setUVTransformToTexture(texture, samplerJson); } let promise = texture.generateTextureFromUri(textureUri, false); textures[textureName] = texture; promisesToLoadResources.push(promise); } if (promisesToLoadResources.length > 0) { Promise.resolve() .then(() => { return Promise.all(promisesToLoadResources); }) .then(() => { this._IterateNodeOfScene(glBoostContext, buffers, json, defaultShader, shaders, textures, glTFVer, resolve, options); }); } else { this._IterateNodeOfScene(glBoostContext, buffers, json, defaultShader, shaders, textures, glTFVer, resolve, options); } } _IterateNodeOfScene(glBoostContext, buffers, json, defaultShader, shaders, textures, glTFVer, resolve, options) { let rootGroup = glBoostContext.createGroup(); rootGroup.userFlavorName = 'glTFFileRoot'; for (let sceneStr in json.scenes) { let sceneJson = json.scenes[sceneStr]; let group = glBoostContext.createGroup(); group.userFlavorName = 'Scene_' + sceneStr; let nodeStr = null; for (let i = 0; i < sceneJson.nodes.length; i++) { nodeStr = sceneJson.nodes[i]; // iterate nodes and load meshes let element = this._recursiveIterateNode(glBoostContext, nodeStr, buffers, json, defaultShader, shaders, textures, glTFVer, options); group.addChild(element); } // register joints hierarchy to skeletal mesh let skeletalMeshes = group.searchElementsByType(M_SkeletalMesh); skeletalMeshes.forEach((skeletalMesh) => { let rootJointGroup = group.searchElementByNameAndType(skeletalMesh.rootJointName, M_Group); if (!rootJointGroup) { // This is a countermeasure when skeleton node does not exist in scene.nodes. rootJointGroup = this._recursiveIterateNode(glBoostContext, skeletalMesh.rootJointName, buffers, json, defaultShader, shaders, textures, glTFVer, options); group.addChild(rootJointGroup); } rootJointGroup._isRootJointGroup = true; skeletalMesh.jointsHierarchy = rootJointGroup; }); // Animation this._loadAnimation(group, buffers, json, glTFVer, options); rootGroup.addChild(group); } rootGroup.allMeshes = rootGroup.searchElementsByType(M_Mesh); if (options && options.loaderExtension && options.loaderExtension.setAssetPropertiesToRootGroup) { options.loaderExtension.setAssetPropertiesToRootGroup(rootGroup, json.asset); } if (options && options.loaderExtension && options.loaderExtension.loadExtensionInfoAndSetToRootGroup) { options.loaderExtension.loadExtensionInfoAndSetToRootGroup(rootGroup, json, glBoostContext); } resolve(rootGroup); } _setTransform(element, nodeJson) { if (nodeJson.translation) { element.translate = new Vector3(nodeJson.translation[0], nodeJson.translation[1], nodeJson.translation[2]); } if (nodeJson.scale) { element.scale = new Vector3(nodeJson.scale[0], nodeJson.scale[1], nodeJson.scale[2]); } if (nodeJson.rotation) { element.quaternion = new Quaternion(nodeJson.rotation[0], nodeJson.rotation[1], nodeJson.rotation[2], nodeJson.rotation[3]); } if (nodeJson.matrix) { element.matrix = new Matrix44$1(nodeJson.matrix, true); } } _recursiveIterateNode(glBoostContext, nodeStr, buffers, json, defaultShader, shaders, textures, glTFVer, options) { var nodeJson = json.nodes[nodeStr]; var group = glBoostContext.createGroup(); group.userFlavorName = nodeStr; this._setTransform(group, nodeJson); if (nodeJson.meshes) { for (let i = 0; i < nodeJson.meshes.length; i++) { // this node has mashes... let meshStr = nodeJson.meshes[i]; let meshJson = json.meshes[meshStr]; let rootJointStr = null; let skinStr = null; if (nodeJson.skeletons) { rootJointStr = nodeJson.skeletons[0]; skinStr = nodeJson.skin; } this._loadMesh(glBoostContext, meshJson, meshStr, buffers, json, defaultShader, rootJointStr, skinStr, shaders, textures, glTFVer, group, options); } } else if (nodeJson.jointName) { let joint = glBoostContext.createJoint(options.isExistJointGizmo); joint.userFlavorName = nodeJson.jointName; group.addChild(joint); } else if (nodeJson.camera) { let cameraStr = nodeJson.camera; let cameraJson = json.cameras[cameraStr]; let camera = null; let centerVec = new Vector3(0.0, 0.0, -1.0); if (json.asset && json.asset.LastSaved_ApplicationVendor) { // For backwards compatibility centerVec = new Vector3(1.0, 0.0, 0.0); } if (cameraJson.type === 'perspective') { let perspective = cameraJson.perspective; camera = glBoostContext.createPerspectiveCamera( { eye: new Vector3(0.0, 0.0, 0), center: centerVec, up: new Vector3(0.0, 1.0, 0.0) }, { fovy: MathUtil.radianToDegree(perspective.yfov), aspect: perspective.aspectRatio ? perspective.aspectRatio : 1.5, zNear: perspective.znear, zFar: perspective.zfar } ); } else if (cameraJson.type === 'orthographic') { let orthographic = cameraJson.orthographic; camera = glBoostContext.createOrthoCamera( { eye: new Vector3(0.0, 0.0, 0), center: centerVec, up: new Vector3(0.0, 1.0, 0.0) }, { xmag: orthographic.xmag, ymag: orthographic.ymag, zNear: orthographic.znear, zFar: orthographic.zfar } ); } camera.userFlavorName = cameraStr + 'Shape'; group.addChild(camera); } else if (nodeJson.extensions) { if (nodeJson.extensions.KHR_materials_common) { if (nodeJson.extensions.KHR_materials_common.light) { const lightStr = nodeJson.extensions.KHR_materials_common.light; const lightJson = json.extensions.KHR_materials_common.lights[lightStr]; let light = null; if (lightJson.type === 'ambient') { let color = lightJson.ambient.color; light = glBoostContext.createAmbientLight(new Vector3(color[0], color[1], color[2])); group.addChild(light); } else if (lightJson.type === 'point') { let color = lightJson.point.color; light = glBoostContext.createPointLight(new Vector3(color[0], color[1], color[2])); this._setTransform(group, nodeJson); group.addChild(light); } else if (lightJson.type === 'directional') { const color = lightJson.directional.color; light = glBoostContext.createDirectionalLight(new Vector3(color[0], color[1], color[2])); light.rotate = new Vector3(0, 0, 0); this._setTransform(group, nodeJson); group.addChild(light); } else if (lightJson.type === 'spot') { const color = lightJson.spot.color; light = glBoostContext.createSpotLight(new Vector3(color[0], color[1], color[2])); light.rotate = new Vector3(0, 0, 0); if (lightJson.spot.falloffAngle) { light.spotCutoffInDegree = lightJson.spot.falloffAngle * 180 / Math.PI; } this._setTransform(group, nodeJson); group.addChild(light); } } } } if (nodeJson.children) { for (let i = 0; i < nodeJson.children.length; i++) { let nodeStr = nodeJson.children[i]; let childElement = this._recursiveIterateNode(glBoostContext, nodeStr, buffers, json, defaultShader, shaders, textures, glTFVer, options); group.addChild(childElement); } } return group; } _loadMesh(glBoostContext, meshJson, meshStr, buffers, json, defaultShader, rootJointStr, skinStr, shaders, textures, glTFVer, group, options) { var mesh = null; var geometry = null; if (rootJointStr) { geometry = glBoostContext.createSkeletalGeometry(); mesh = glBoostContext.createSkeletalMesh(geometry, null, rootJointStr); let skin = json.skins[skinStr]; mesh.bindShapeMatrix = new Matrix44$1(skin.bindShapeMatrix, true); mesh.jointNames = skin.jointNames; let inverseBindMatricesAccessorStr = skin.inverseBindMatrices; mesh.inverseBindMatrices = this._accessBinary(inverseBindMatricesAccessorStr, json, buffers); } else { geometry = glBoostContext.createGeometry(); mesh = glBoostContext.createMesh(geometry); } mesh.userFlavorName = meshStr; if (!(options.ignoreMeshList != null) || options.ignoreMeshList.indexOf(mesh.userFlavorName) === -1) { // if the mesh name is not in ignore list, add it to the group. group.addChild(mesh); } if (options && options.isMeshTransparentAsDefault || options && options.defaultStates && options.defaultStates.isTransparent) { mesh.isTransparent = true; } let _indicesArray = []; let _positions = []; let _normals = []; let vertexData = { position: _positions, normal: _normals, components: {}, componentBytes: {}, componentType: {} }; let additional = { 'joint': [], 'weight': [], 'texcoord': [], 'color': [] }; let dataViewMethodDic = {}; let materials = []; let indicesAccumulatedLength = 0; for (let i = 0; i < meshJson.primitives.length; i++) { let primitiveJson = meshJson.primitives[i]; // Geometry let positionsAccessorStr = primitiveJson.attributes.POSITION; let positions = this._accessBinary(positionsAccessorStr, json, buffers, false, true); _positions[i] = positions; vertexData.components.position = this._checkComponentNumber(positionsAccessorStr, json); vertexData.componentBytes.position = this._checkBytesPerComponent(positionsAccessorStr, json); vertexData.componentType.position = this._getDataType(positionsAccessorStr, json); dataViewMethodDic.position = this._checkDataViewMethod(positionsAccessorStr, json); let indices = null; if (typeof primitiveJson.indices !== 'undefined') { let indicesAccessorStr = primitiveJson.indices; indices = this._accessBinary(indicesAccessorStr, json, buffers); for (let j=0; j{ let isMatch = this.isTargetMatch(statesInfo, elem, target); if (isMatch) { elem.isTransparent = statesInfo.isTransparent !== void 0 ? statesInfo.isTransparent : false; if (statesInfo.states) { material.states = statesInfo.states; } material.globalStatesUsage = statesInfo.globalStatesUsage !== void 0 ? statesInfo.globalStatesUsage : GLBoost$1.GLOBAL_STATES_USAGE_IGNORE; } }); } } } } texcoords = this._loadMaterial(glBoostContext, buffers, json, vertexData, indices, material, materialStr, positions, dataViewMethodDic, additional, texcoords, texcoords0AccessorStr, geometry, defaultShader, shaders, textures, i, glTFVer, group, options); materials.push(material); } else { let material = null; if (options.loaderExtension && options.loaderExtension.createClassicMaterial) { material = options.loaderExtension.createClassicMaterial(glBoostContext); } else { material = glBoostContext.createClassicMaterial(); } if (defaultShader) { material.shaderClass = defaultShader; } else { material.baseColor = new Vector4$1(0.5, 0.5, 0.5, 1); } materials.push(material); } } if (meshJson.primitives.length > 1) { let lengthDic = {index: 0, position: 0, normal: 0, color: 0, joint: 0, weight: 0, texcoord: 0}; for (let i = 0; i < meshJson.primitives.length; i++) { //lengthDic.index += _indicesArray[i].length; lengthDic.position += _positions[i].length; if (_normals[i]) { lengthDic.normal += _normals[i].length; } if (typeof additional['color'][i] !== 'undefined') { lengthDic.color += additional['color'][i].length; } if (typeof additional['joint'][i] !== 'undefined') { lengthDic.joint += additional['joint'][i].length; } if (typeof additional['weight'][i] !== 'undefined') { lengthDic.weight += additional['weight'][i].length; } if (typeof additional['texcoord'][i] !== 'undefined') { lengthDic.texcoord += additional['texcoord'][i].length; } } function getTypedArray(dataViewMethod, length) { let vertexAttributeArray = null; if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(length); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(length); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = new Int16Array(length); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = new Uint16Array(length); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = new Int32Array(length); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = new Uint32Array(length); } else if (dataViewMethod === 'getFloat32') { vertexAttributeArray = new Float32Array(length); } return vertexAttributeArray; } for (let attribName in dataViewMethodDic) { let newTypedArray = getTypedArray(dataViewMethodDic[attribName], lengthDic[attribName]); let offset = 0; for (let i = 0; i < meshJson.primitives.length; i++) { let array = null; if (attribName === 'position') { array = _positions[i]; } else if (attribName === 'normal') { array = _normals[i]; } else if (attribName === 'color') { array = additional['color'][i]; } else if (attribName === 'joint') { array = additional['joint'][i]; } else if (attribName === 'weight') { array = additional['weight'][i]; } else if (attribName === 'texcoord') { array = additional['texcoord'][i]; } if (array) { newTypedArray.set(array, offset); offset += array.length; } } if (attribName === 'position') { vertexData.position = newTypedArray; } else if (attribName === 'normal') { vertexData.normal = newTypedArray; } else if (attribName === 'color') { additional['color'] = newTypedArray; } else if (attribName === 'joint') { additional['joint'] = newTypedArray; } else if (attribName === 'weight') { additional['weight'] = newTypedArray; } else if (attribName === 'texcoord') { additional['texcoord'] = newTypedArray; } } } else { vertexData.position = _positions[0]; vertexData.normal = _normals[0]; additional['color'] = additional['color'][0]; additional['joint'] = additional['joint'][0]; additional['weight'] = additional['weight'][0]; additional['texcoord'] = additional['texcoord'][0]; } if (typeof vertexData.normal === 'undefined' || vertexData.normal.length === 0) { delete vertexData.normal; } if (typeof additional['color'] === 'undefined' || additional['color'].length === 0) { delete additional['color']; } if (typeof additional['joint'] === 'undefined' || additional['joint'].length === 0) { delete additional['joint']; } if (typeof additional['weight'] === 'undefined' || additional['weight'].length === 0) { delete additional['weight']; } if (typeof additional['texcoord'] === 'undefined' || additional['texcoord'].length === 0) { delete additional['texcoord']; } if (_indicesArray.length === 0) { _indicesArray = null; } geometry.setVerticesData(ArrayUtil.merge(vertexData, additional), _indicesArray); geometry.materials = materials; return mesh; } _isKHRMaterialsCommon(materialJson) { if (typeof materialJson.extensions !== 'undefined' && typeof materialJson.extensions.KHR_materials_common !== 'undefined') { return true; } else { return false; } } _loadMaterial(glBoostContext, buffers, json, vertexData, indices, material, materialStr, positions, dataViewMethodDic, additional, texcoords, texcoords0AccessorStr, geometry, defaultShader, shaders, textures, idx, glTFVer, group, options) { let materialJson = json.materials[materialStr]; material.userFlavorName = materialJson.name; let originalMaterialJson = materialJson; if (this._isKHRMaterialsCommon(materialJson)) { materialJson = materialJson.extensions.KHR_materials_common; } let enables = []; if (options.isBlend) { enables.push(3042); } if (options.isDepthTest) { enables.push(2929); } material.states.enable = material.states.enable.concat(enables); // Remove duplicated values material.states.enable = material.states.enable.filter(function (x, i, self) { return self.indexOf(x) === i; }); if (options && options.statesOfElements) { for (let statesInfo of options.statesOfElements) { if (statesInfo.opacity) { group.opacity = statesInfo.opacity; } } } if (options.isBlend && options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (material.states.functions.blendFuncSeparate === void 0) { material.states.functions.blendFuncSeparate = [1, 771, 1, 771]; } } material.globalStatesUsage = GLBoost$1.GLOBAL_STATES_USAGE_IGNORE; // Diffuse Texture if (texcoords0AccessorStr) { texcoords = this._accessBinary(texcoords0AccessorStr, json, buffers, false, true); additional['texcoord'][idx] = texcoords; vertexData.components.texcoord = this._checkComponentNumber(texcoords0AccessorStr, json); vertexData.componentBytes.texcoord = this._checkBytesPerComponent(texcoords0AccessorStr, json); vertexData.componentType.texcoord = this._getDataType(texcoords0AccessorStr, json); dataViewMethodDic.texcoord = this._checkDataViewMethod(texcoords0AccessorStr, json); let setTextures = (values, isParameter)=> { for (let valueName in values) { let value = null; if (isParameter) { value = values[valueName].value; if (typeof value === 'undefined') { continue; } } else { value = values[valueName]; } if (glTFVer >= 1.1) { value = value[0]; } if (typeof value === 'string') { let textureStr = value; let texturePurpose; if (valueName === 'diffuse' || (materialJson.technique === "CONSTANT" && valueName === 'ambient')) { texturePurpose = GLBoost$1.TEXTURE_PURPOSE_DIFFUSE; } else if (valueName === 'emission' && textureStr.match(/_normal$/)) { texturePurpose = GLBoost$1.TEXTURE_PURPOSE_NORMAL; } else { texturePurpose = GLBoost$1.TEXTURE_PURPOSE_OTHERS; } let texture = textures[textureStr]; let isNeededToMultiplyAlphaToColorOfTexture = false; if (options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (options.isTextureImageToLoadPreMultipliedAlphaAsDefault) ; else { isNeededToMultiplyAlphaToColorOfTexture = true; } } else { // if is NOT Needed To Multiply AlphaToColor Of PixelOutput if (options.isTextureImageToLoadPreMultipliedAlphaAsDefault) ; } if (options && options.statesOfElements) { for (let statesInfo of options.statesOfElements) { if (statesInfo.targets) { for (let target of statesInfo.targets) { let isMatch = false; isMatch = this.isTargetMatch(statesInfo, group, target); if (isMatch) { if (options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (statesInfo.isTextureImageToLoadPreMultipliedAlpha) ; else { isNeededToMultiplyAlphaToColorOfTexture = true; } } else { // if is NOT Needed To Multiply AlphaToColor Of PixelOutput if (statesInfo.isTextureImageToLoadPreMultipliedAlpha) ; } } //texture.setParameter('UNPACK_PREMULTIPLY_ALPHA_WEBGL', isNeededToMultiplyAlphaToColorOfTexture); // texture.loadWebGLTexture(); } } } } material.setTexture(texture, texturePurpose); texture.toMultiplyAlphaToColorPreviously = isNeededToMultiplyAlphaToColorOfTexture; } } }; setTextures(materialJson.values, false); if (materialJson.technique && json.techniques) { if (typeof json.techniques[materialJson.technique] !== "undefined") { setTextures(json.techniques[materialJson.technique].parameters, true); } } } else { if (typeof vertexData.components.texcoord !== 'undefined') { // If texture coordinates existed even once in the previous loop let emptyTexcoords = []; let componentN = vertexData.components.position; let length = positions.length / componentN; for (let k = 0; k < length; k++) { emptyTexcoords.push(0); emptyTexcoords.push(0); } additional['texcoord'][idx] = new Float32Array(emptyTexcoords); vertexData.components.texcoord = 2; vertexData.componentBytes.texcoord = 4; dataViewMethodDic.texcoord = 'getFloat32'; } } for (let valueName in materialJson.values) { let value = materialJson.values[valueName]; if (typeof value !== 'string') { material[valueName + 'Color'] = MathClassUtil.arrayToVectorOrMatrix(value); } if (valueName === 'transparent') { material.isTransparent = value; let enables = [3042]; material.states.enable = material.states.enable.concat(enables); } if (valueName === 'transparency') { material.baseColor.w = 1.0 - value; material.diffuseColor.w = 1.0 - value; material.specularColor.w = 1.0 - value; material.ambientColor.w = 1.0 - value; } } if (indices !== null) { material.setVertexN(geometry, indices.length); } let techniqueStr = materialJson.technique; if (defaultShader) { material.shaderClass = defaultShader; } else if (this._isKHRMaterialsCommon(originalMaterialJson) && material.className.indexOf('PBR') === -1) { switch (techniqueStr) { case 'CONSTANT': if (options.loaderExtension && options.loaderExtension.getDecalShader) { material.shaderClass = options.loaderExtension.getDecalShader(); } else { material.shaderClass = DecalShader; } break; case 'LAMBERT': if (options.loaderExtension && options.loaderExtension.getLambertShader) { material.shaderClass = options.loaderExtension.getLambertShader(); } else { material.shaderClass = LambertShader; } break; case 'PHONG': if (options.loaderExtension && options.loaderExtension.getPhongShader) { material.shaderClass = options.loaderExtension.getPhongShader(); } else { material.shaderClass = PhongShader; } break; } } else { if (typeof json.techniques !== 'undefined') { this._loadTechnique(glBoostContext, json, techniqueStr, material, materialJson, shaders, glTFVer); } else if (material.className.indexOf('PBR') === -1) { if (options.loaderExtension && options.loaderExtension.getDecalShader) { material.shaderClass = options.loaderExtension.getDecalShader(); } else { material.shaderClass = DecalShader; } } } if (options && options.statesOfElements) { for (let statesInfo of options.statesOfElements) { if (statesInfo.targets) { for (let target of statesInfo.targets) { let isMatch = false; isMatch = this.isTargetMatch(statesInfo, group, target); if (isMatch) { if (statesInfo.shaderClass) { material.shaderClass = statesInfo.shaderClass; } } } } } } return texcoords; } isTargetMatch(statesInfo, element, target) { let specifyMethod = statesInfo.specifyMethod !== void 0 ? statesInfo.specifyMethod : GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME; if (typeof statesInfo.specifyMethod === 'string') { statesInfo.specifyMethod = GLBoost$1[statesInfo.specifyMethod]; } const isTargetMatchInner = function(specifyMethod, element, target) { let isMatch = false; switch (specifyMethod) { case GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME: isMatch = element.userFlavorName === target; break; case GLBoost$1.QUERY_TYPE_INSTANCE_NAME: isMatch = element.instanceName === target; break; case GLBoost$1.QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR: isMatch = element.instanceNameWithUserFlavor === target; break; } return isMatch; }; let isMatch = isTargetMatchInner(specifyMethod, element, target); return isMatch; } _loadTechnique(glBoostContext, json, techniqueStr, material, materialJson, shaders, glTFVer) { let techniqueJson = json.techniques[techniqueStr]; let programStr = techniqueJson.program; let uniformsJson = techniqueJson.uniforms; let parametersJson = techniqueJson.parameters; let attributesJson = techniqueJson.attributes; let attributes = {}; for (let attributeName in attributesJson) { //attributes[attributesJson[attributeName]] = attributeName; let parameterName = attributesJson[attributeName]; let parameterJson = parametersJson[parameterName]; attributes[attributeName] = parameterJson.semantic; } let uniforms = {}; let textureNames = {}; for (let uniformName in uniformsJson) { let parameterName = uniformsJson[uniformName]; let parameterJson = parametersJson[parameterName]; if (typeof parameterJson.semantic !== 'undefined') { uniforms[uniformName] = parameterJson.semantic; } else { let value = null; if (typeof materialJson.values !== 'undefined' && typeof materialJson.values[parameterName] !== 'undefined') { value = materialJson.values[parameterName]; } else { value = parameterJson.value; } switch (parameterJson.type) { case 5126: uniforms[uniformName] = (glTFVer < 1.1) ? value : value[0]; break; case 35664: uniforms[uniformName] = new Vector2(value[0], value[1]); break; case 35665: uniforms[uniformName] = new Vector3(value[0], value[1], value[2]); break; case 35666: uniforms[uniformName] = new Vector4$1(value[0], value[1], value[2], value[3]); break; case 5124: uniforms[uniformName] = (glTFVer < 1.1) ? value : value[0]; break; case 35667: uniforms[uniformName] = new Vector2(value[0], value[1]); break; case 35668: uniforms[uniformName] = new Vector3(value[0], value[1], value[2]); break; case 35669: uniforms[uniformName] = new Vector4$1(value[0], value[1], value[2], value[3]); break; case 35678: uniforms[uniformName] = 'TEXTURE'; textureNames[uniformName] = (glTFVer < 1.1) ? value : value[0]; break; } } } if (techniqueJson.states) { if (techniqueJson.states.functions) { for (let functionName in techniqueJson.states.functions) { if (!Array.isArray(techniqueJson.states.functions[functionName])) { techniqueJson.states.functions[functionName] = [techniqueJson.states.functions[functionName]]; } } } material.states = techniqueJson.states; } this._loadProgram(glBoostContext, json, programStr, material, shaders, attributes, uniforms, textureNames); } _loadProgram(glBoostContext, json, programStr, material, shaders, attributes, uniforms, textureNames) { let programJson = json.programs[programStr]; let fragmentShaderStr = programJson.fragmentShader; let vertexShaderStr = programJson.vertexShader; let fragmentShaderText = shaders[fragmentShaderStr].shaderText; let vertexShaderText = shaders[vertexShaderStr].shaderText; material.shaderInstance = new FreeShader(glBoostContext.__system, vertexShaderText, fragmentShaderText, attributes, uniforms, textureNames); } _loadAnimation(element, buffers, json, glTFVer, options) { let animationJson = null; for (let anim in json.animations) { animationJson = json.animations[anim]; if (animationJson) { for (let i = 0; i < animationJson.channels.length; i++) { let channelJson = animationJson.channels[i]; if (!channelJson) { continue; } let targetMeshStr = channelJson.target.id; let targetPathStr = channelJson.target.path; let samplerStr = channelJson.sampler; let samplerJson = animationJson.samplers[samplerStr]; let animInputAccessorStr = null; let animOutputAccessorStr = null; let animInputStr = samplerJson.input; let animOutputStr = samplerJson.output; animInputAccessorStr = animationJson.parameters[animInputStr]; animOutputAccessorStr = animationJson.parameters[animOutputStr]; let interpolationMethod = GLBoost$1.INTERPOLATION_LINEAR; if (options.loaderExtension && options.loaderExtension.getAnimationInterpolationMethod) { interpolationMethod = options.loaderExtension.getAnimationInterpolationMethod(samplerJson.interpolation); } let animInputArray = this._accessBinary(animInputAccessorStr, json, buffers); let animOutputArray = null; if (targetPathStr === 'translation') { animOutputArray = this._accessBinary(animOutputAccessorStr, json, buffers); } else if (targetPathStr === 'rotation') { animOutputArray = this._accessBinary(animOutputAccessorStr, json, buffers, true); } else { animOutputArray = this._accessBinary(animOutputAccessorStr, json, buffers); } let animationAttributeName = ''; if (targetPathStr === 'translation') { animationAttributeName = 'translate'; } else if (targetPathStr === 'rotation') { animationAttributeName = 'quaternion'; } else { animationAttributeName = targetPathStr; } let hitElement = element.searchElement(targetMeshStr); if (hitElement) { hitElement.setAnimationAtLine('time', animationAttributeName, animInputArray, animOutputArray, interpolationMethod); hitElement.setActiveAnimationLine('time'); } } } } } _accessBinaryAsShader(bufferViewStr, json, arrayBuffer) { let bufferViewJson = json.bufferViews[bufferViewStr]; let byteOffset = bufferViewJson.byteOffset; let byteLength = bufferViewJson.byteLength; let arrayBufferSliced = arrayBuffer.slice(byteOffset, byteOffset + byteLength); return DataUtil.arrayBufferToString(arrayBufferSliced); } _sliceBufferViewToArrayBuffer(json, bufferViewStr, arrayBuffer) { let bufferViewJson = json.bufferViews[bufferViewStr]; let byteOffset = (bufferViewJson.byteOffset != null) ? bufferViewJson.byteOffset : 0; let byteLength = bufferViewJson.byteLength; let arrayBufferSliced = arrayBuffer.slice(byteOffset, byteOffset + byteLength); return arrayBufferSliced; } _accessBinaryAsImage(bufferViewStr, json, arrayBuffer, mimeType) { let arrayBufferSliced = this._sliceBufferViewToArrayBuffer(json, bufferViewStr, arrayBuffer); return this._accessArrayBufferAsImage(arrayBufferSliced, mimeType); } _accessArrayBufferAsImage(arrayBuffer, imageType) { let bytes = new Uint8Array(arrayBuffer); let binaryData = ''; for (let i = 0, len = bytes.byteLength; i < len; i++) { binaryData += String.fromCharCode(bytes[i]); } let imgSrc = ''; if (imageType === 'image/jpeg' || imageType.toLowerCase() === 'jpg' || imageType.toLowerCase() === 'jpeg') { imgSrc = "data:image/jpeg;base64,"; } else if (imageType == 'image/png' || imageType.toLowerCase() === 'png') { imgSrc = "data:image/png;base64,"; } else if (imageType == 'image/gif' || imageType.toLowerCase() === 'gif') { imgSrc = "data:image/gif;base64,"; } else if (imageType == 'image/bmp' || imageType.toLowerCase() === 'bmp') { imgSrc = "data:image/bmp;base64,"; } else { imgSrc = "data:image/unknown;base64,"; } let dataUrl = imgSrc + DataUtil.btoa(binaryData); return dataUrl; } static _isSystemLittleEndian() { return !!(new Uint8Array((new Uint16Array([0x00ff])).buffer))[0]; } _checkComponentNumber(accessorStr, json) { var accessorJson = json.accessors[accessorStr]; var componentN = 0; switch (accessorJson.type) { case 'SCALAR': componentN = 1; break; case 'VEC2': componentN = 2; break; case 'VEC3': componentN = 3; break; case 'VEC4': componentN = 4; break; case 'MAT4': componentN = 16; break; } return componentN; } _checkBytesPerComponent(accessorStr, json) { var accessorJson = json.accessors[accessorStr]; var bytesPerComponent = 0; switch (accessorJson.componentType) { case 5120: // gl.BYTE bytesPerComponent = 1; break; case 5121: // gl.UNSIGNED_BYTE bytesPerComponent = 1; break; case 5122: // gl.SHORT bytesPerComponent = 2; break; case 5123: // gl.UNSIGNED_SHORT bytesPerComponent = 2; break; case 5124: // gl.INT bytesPerComponent = 4; break; case 5125: // gl.UNSIGNED_INT bytesPerComponent = 4; break; case 5126: // gl.FLOAT bytesPerComponent = 4; break; default: break; } return bytesPerComponent; } _checkDataViewMethod(accessorStr, json) { var accessorJson = json.accessors[accessorStr]; var dataViewMethod = ''; switch (accessorJson.componentType) { case 5120: // gl.BYTE dataViewMethod = 'getInt8'; break; case 5121: // gl.UNSIGNED_BYTE dataViewMethod = 'getUint8'; break; case 5122: // gl.SHORT dataViewMethod = 'getInt16'; break; case 5123: // gl.UNSIGNED_SHORT dataViewMethod = 'getUint16'; break; case 5124: // gl.INT dataViewMethod = 'getInt32'; break; case 5125: // gl.UNSIGNED_INT dataViewMethod = 'getUint32'; break; case 5126: // gl.FLOAT dataViewMethod = 'getFloat32'; break; default: break; } return dataViewMethod; } _getDataType(accessorStr, json) { var accessorJson = json.accessors[accessorStr]; return accessorJson.componentType; } _adjustByteAlign(typedArrayClass, arrayBuffer, alignSize, byteOffset, length) { if (( byteOffset % alignSize ) != 0) { return new typedArrayClass(arrayBuffer.slice(byteOffset), 0, length); } else { return new typedArrayClass(arrayBuffer, byteOffset, length); } } _accessBinary(accessorStr, json, buffers, quaternionIfVec4 = false, toGetAsTypedArray = false) { var accessorJson = json.accessors[accessorStr]; var bufferViewStr = accessorJson.bufferView; var bufferViewJson = json.bufferViews[bufferViewStr]; var byteOffset = bufferViewJson.byteOffset + accessorJson.byteOffset; var bufferStr = bufferViewJson.buffer; var arrayBuffer = buffers[bufferStr]; let componentN = this._checkComponentNumber(accessorStr, json); let bytesPerComponent = this._checkBytesPerComponent(accessorStr, json); var dataViewMethod = this._checkDataViewMethod(accessorStr, json); var byteLength = bytesPerComponent * componentN * accessorJson.count; var vertexAttributeArray = []; if (toGetAsTypedArray) { if (GLTFLoader._isSystemLittleEndian()) { if (dataViewMethod === 'getFloat32') { vertexAttributeArray = this._adjustByteAlign(Float32Array, arrayBuffer, 4, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(arrayBuffer, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(arrayBuffer, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = this._adjustByteAlign(Int16Array, arrayBuffer, 2, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = this._adjustByteAlign(Uint16Array, arrayBuffer, 2, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = this._adjustByteAlign(Int32Array, arrayBuffer, 4, byteOffset, byteLength / bytesPerComponent); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = this._adjustByteAlign(Uint32Array, arrayBuffer, 4, byteOffset, byteLength / bytesPerComponent); } } else { let dataView = new DataView(arrayBuffer, byteOffset, byteLength); let byteDelta = bytesPerComponent * componentN; let littleEndian = true; for (let pos = 0; pos < byteLength; pos += byteDelta) { switch (accessorJson.type) { case 'SCALAR': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); break; case 'VEC2': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent, littleEndian)); break; case 'VEC3': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent * 2, littleEndian)); break; case 'VEC4': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent * 2, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + bytesPerComponent * 3, littleEndian)); break; } } if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(vertexAttributeArray); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = new Int16Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = new Uint16Array(vertexAttributeArray); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = new Int32Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = new Uint32Array(vertexAttributeArray); } else if (dataViewMethod === 'getFloat32') { vertexAttributeArray = new Float32Array(vertexAttributeArray); } } } else { let dataView = new DataView(arrayBuffer, byteOffset, byteLength); let byteDelta = bytesPerComponent * componentN; let littleEndian = true; for (let pos = 0; pos < byteLength; pos += byteDelta) { switch (accessorJson.type) { case 'SCALAR': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); break; case 'VEC2': vertexAttributeArray.push(new Vector2( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent, littleEndian) )); break; case 'VEC3': vertexAttributeArray.push(new Vector3( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent*2, littleEndian) )); break; case 'VEC4': if (quaternionIfVec4) { vertexAttributeArray.push(new Quaternion( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent*2, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent*3, littleEndian) )); } else { vertexAttributeArray.push(new Vector4$1( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent*2, littleEndian), dataView[dataViewMethod](pos+bytesPerComponent*3, littleEndian) )); } break; case 'MAT4': let matrixComponents = []; for (let i=0; i<16; i++) { matrixComponents[i] = dataView[dataViewMethod](pos+bytesPerComponent*i, littleEndian); } vertexAttributeArray.push(new Matrix44$1(matrixComponents, true)); break; } } } return vertexAttributeArray; } } GLBoost$1["GLTFLoader"] = GLTFLoader; // let singleton$7 = Symbol(); let singletonEnforcer$4 = Symbol(); /** * This is a loader class of glTF2 file format. You can see more detail of glTF2 format at https://github.com/KhronosGroup/glTF . */ class GLTF2Loader { /** * The constructor of GLTFLoader class. But you cannot use this constructor directly because of this class is a singleton class. Use getInstance() static method. * @param enforcer a Symbol to forbid calling this constructor directly */ constructor(enforcer ) { if (enforcer !== singletonEnforcer$4) { throw new Error("This is a Singleton class. get the instance using 'getInstance' static method."); } } _getOptions(defaultOptions, json, options) { if (json.asset && json.asset.extras && json.asset.extras.loadOptions) { for (let optionName in json.asset.extras.loadOptions) { defaultOptions[optionName] = json.asset.extras.loadOptions[optionName]; } } for (let optionName in options) { defaultOptions[optionName] = options[optionName]; } if (defaultOptions.loaderExtension && typeof defaultOptions.loaderExtension === "string") { defaultOptions.loaderExtension = GLBoost$1[options.loaderExtension].getInstance(); } if (defaultOptions.statesOfElements) { for (let state of defaultOptions.statesOfElements) { if (state.shaderClass && typeof state.shaderClass === "string") { state.shaderClass = GLBoost$1[state.shaderClass]; } } } return defaultOptions; } /** * The static method to get singleton instance of this class. * @return The singleton instance of GLTFLoader class */ static getInstance() { if (!this[singleton$7]) { this[singleton$7] = new GLTF2Loader(singletonEnforcer$4); } return this[singleton$7]; } /** * the method to load glTF2 file. * @param uri uri of glTF file * @param options - opition data for loading * @return */ loadGLTF(uri , options = {}) { let defaultOptions = { files: { // "foo.gltf": content of file as ArrayBuffer, // "foo.bin": content of file as ArrayBuffer, // "boo.png": content of file as ArrayBuffer }, loaderExtension: null, isNeededToMultiplyAlphaToColorOfPixelOutput: true, isTextureImageToLoadPreMultipliedAlphaAsDefault: false, isExistJointGizmo: false, isBlend: false, isDepthTest: true, defaultShaderClass: null, isMeshTransparentAsDefault: false, statesOfElements: [ { targets: [], //["name_foo", "name_boo"], specifyMethod: GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME, // GLBoost.QUERY_TYPE_INSTANCE_NAME // GLBoost.QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR states: { enable: [ // 3042, // BLEND ], functions: { //"blendFuncSeparate": [1, 0, 1, 0], } }, isTransparent: true, opacity: 1.0, shaderClass: DecalShader, // LambertShader // PhongShader isTextureImageToLoadPreMultipliedAlpha: false, globalStatesUsage: GLBoost$1.GLOBAL_STATES_USAGE_IGNORE // GLBoost.GLOBAL_STATES_USAGE_DO_NOTHING // GLBoost.GLOBAL_STATES_USAGE_INCLUSIVE // GLBoost.GLOBAL_STATES_USAGE_EXCLUSIVE } ], extendedJson: null // URI string / JSON Object / ArrayBuffer }; (function() { const userAgent = window.navigator.userAgent.toLowerCase(); if(userAgent.indexOf('safari') !== -1) { var cors_api_host = 'cors-anywhere.glboost.org'; var cors_api_url = 'https://' + cors_api_host + '/'; var slice = [].slice; var origin = window.location.protocol + '//' + window.location.host; var open = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function() { var args = slice.call(arguments); var targetOrigin = /^https?:\/\/([^\/]+)/i.exec(args[1]); if (targetOrigin && targetOrigin[0].toLowerCase() !== origin && targetOrigin[1] !== cors_api_host) { args[1] = cors_api_url + args[1]; } return open.apply(this, args); }; } })(); if (options && options.files) { for (let fileName in options.files) { const splitted = fileName.split('.'); const fileExtension = splitted[splitted.length - 1]; if (fileExtension === 'gltf' || fileExtension === 'glb') { return new Promise((resolve, response)=>{ this._checkArrayBufferOfGltf(options.files[fileName], null, options, defaultOptions, resolve); }, (reject, error)=>{ }); } } } return DataUtil.loadResourceAsync(uri, true, (resolve, response)=>{ var arrayBuffer = response; if (options.extendedJson) { fetch(options.extendedJson).then((_response)=> { _response.json().then((json)=>{ options.extendedJson = json; this._checkArrayBufferOfGltf(arrayBuffer, uri, options, defaultOptions, resolve); }); }).then((json)=> { //this._checkArrayBufferOfGltf(arrayBuffer, uri, options, defaultOptions, resolve); console.log("Result of ladding extended JSON"); }); } else { this._checkArrayBufferOfGltf(arrayBuffer, uri, options, defaultOptions, resolve); } }, (reject, error)=>{} ); } _checkArrayBufferOfGltf(arrayBuffer, uri, options, defaultOptions, resolve) { this._materials = []; let dataView = new DataView(arrayBuffer, 0, 20); let isLittleEndian = true; // Magic field let magic = dataView.getUint32(0, isLittleEndian); // 0x46546C67 is 'glTF' in ASCII codes. if (magic !== 0x46546C67) { this._loadAsTextJson(arrayBuffer, uri, options, defaultOptions, resolve); } else { this._loadAsBinaryJson(dataView, uri, isLittleEndian, arrayBuffer, options, defaultOptions, resolve); } } _loadAsBinaryJson(dataView, uri, isLittleEndian, arrayBuffer, options, defaultOptions, resolve) { let gltfVer = dataView.getUint32(4, isLittleEndian); if (gltfVer !== 2) { reject('invalid version field in this binary glTF file.'); } let lengthOfThisFile = dataView.getUint32(8, isLittleEndian); let lengthOfJSonChunkData = dataView.getUint32(12, isLittleEndian); let chunkType = dataView.getUint32(16, isLittleEndian); // 0x4E4F534A means JSON format (0x4E4F534A is 'JSON' in ASCII codes) if (chunkType !== 0x4E4F534A) { reject('invalid chunkType of chunk0 in this binary glTF file.'); } let arrayBufferJSonContent = arrayBuffer.slice(20, 20 + lengthOfJSonChunkData); let gotText = DataUtil.arrayBufferToString(arrayBufferJSonContent); let gltfJson = JSON.parse(gotText); options = this._getOptions(defaultOptions, gltfJson, options); let arrayBufferBinary = arrayBuffer.slice(20 + lengthOfJSonChunkData + 8); let basePath = null; if (uri) { //Set the location of glb file as basePath basePath = uri.substring(0, uri.lastIndexOf('/')) + '/'; } if (gltfJson.asset.extras === undefined) { gltfJson.asset.extras = {}; } this._mergeExtendedJson(gltfJson, options.extendedJson); gltfJson.asset.extras.basePath = basePath; let promise = this._loadInner(arrayBufferBinary, basePath, gltfJson, options); promise.then((gltfJson) => { console.log('Resoureces loading done!'); resolve(gltfJson[0][0]); }); } _loadAsTextJson(arrayBuffer, uri, options, defaultOptions, resolve) { let gotText = DataUtil.arrayBufferToString(arrayBuffer); let basePath = null; if (uri) { //Set the location of gltf file as basePath basePath = uri.substring(0, uri.lastIndexOf('/')) + '/'; } let gltfJson = JSON.parse(gotText); if (gltfJson.asset.extras === undefined) { gltfJson.asset.extras = {}; } options = this._getOptions(defaultOptions, gltfJson, options); this._mergeExtendedJson(gltfJson, options.extendedJson); gltfJson.asset.extras.basePath = basePath; let promise = this._loadInner(null, basePath, gltfJson, options); promise.then((gltfJson) => { console.log('Resoureces loading done!'); resolve(gltfJson[0][0]); }); } _mergeExtendedJson(gltfJson, extendedData) { let extendedJson = null; if (extendedData instanceof ArrayBuffer) { const extendedJsonStr = DataUtil.arrayBufferToString(extendedData); extendedJson = JSON.parse(extendedJsonStr); } else if (typeof extendedData === 'string') { extendedJson = JSON.parse(extendedData); extendedJson = extendedJson; } else if (typeof extendedData === 'object') { extendedJson = extendedData; } Object.assign(gltfJson, extendedJson); } _loadInner(arrayBufferBinary, basePath, gltfJson, options) { let promises = []; let resources = { shaders: [], buffers: [], images: [] }; promises.push(this._loadResources(arrayBufferBinary, basePath, gltfJson, options, resources)); promises.push(new Promise(((resolve, reject) => { this._loadJsonContent(gltfJson, resources, options); resolve(); }))); return Promise.all(promises); } _loadJsonContent(gltfJson, resources, options) { // Scene this._loadDependenciesOfScenes(gltfJson); // Node this._loadDependenciesOfNodes(gltfJson); // Node Transformation // this._loadTransformationsOfNodes(gltfJson); // Mesh this._loadDependenciesOfMeshes(gltfJson); // Material this._loadDependenciesOfMaterials(gltfJson); // Texture this._loadDependenciesOfTextures(gltfJson); // Joint this._loadDependenciesOfJoints(gltfJson); // Animation this._loadDependenciesOfAnimations(gltfJson); // Accessor this._loadDependenciesOfAccessors(gltfJson); // BufferView this._loadDependenciesOfBufferViews(gltfJson); if (gltfJson.asset === void 0) { gltfJson.asset = {}; } if (gltfJson.asset.extras === void 0) { gltfJson.asset.extras = {}; } gltfJson.asset.extras.glboostOptions = options; } _loadDependenciesOfScenes(gltfJson) { for (let scene of gltfJson.scenes) { scene.nodesIndices = scene.nodes.concat(); for (let i in scene.nodesIndices) { scene.nodes[i] = gltfJson.nodes[scene.nodesIndices[i]]; } } } _loadDependenciesOfNodes(gltfJson) { for (let node of gltfJson.nodes) { // Hierarchy if (node.children) { node.childrenIndices = node.children.concat(); node.children = []; for (let i in node.childrenIndices) { node.children[i] = gltfJson.nodes[node.childrenIndices[i]]; } } // Mesh if (node.mesh !== void 0 && gltfJson.meshes !== void 0) { node.meshIndex = node.mesh; node.mesh = gltfJson.meshes[node.meshIndex]; } // Skin if (node.skin !== void 0 && gltfJson.skins !== void 0) { node.skinIndex = node.skin; node.skin = gltfJson.skins[node.skinIndex]; if (node.mesh.extras === void 0) { node.mesh.extras = {}; } node.mesh.extras._skin = node.skin; } // Camera if (node.camera !== void 0 && gltfJson.cameras !== void 0) { node.cameraIndex = node.camera; node.camera = gltfJson.cameras[node.cameraIndex]; } } } _loadDependenciesOfMeshes(gltfJson) { // Mesh for (let mesh of gltfJson.meshes) { for (let primitive of mesh.primitives) { if (primitive.material !== void 0) { primitive.materialIndex = primitive.material; primitive.material = gltfJson.materials[primitive.materialIndex]; } primitive.attributesindex = Object.assign({}, primitive.attributes); for (let attributeName in primitive.attributesindex) { if (primitive.attributesindex[attributeName] >= 0) { let accessor = gltfJson.accessors[primitive.attributesindex[attributeName]]; accessor.extras = { toGetAsTypedArray: true }; primitive.attributes[attributeName] = accessor; } else { primitive.attributes[attributeName] = void 0; } } if (primitive.indices !== void 0) { primitive.indicesIndex = primitive.indices; primitive.indices = gltfJson.accessors[primitive.indicesIndex]; } } } } _loadDependenciesOfMaterials(gltfJson) { // Material if (gltfJson.materials) { for (let material of gltfJson.materials) { if (material.pbrMetallicRoughness) { let baseColorTexture = material.pbrMetallicRoughness.baseColorTexture; if (baseColorTexture !== void 0) { baseColorTexture.texture = gltfJson.textures[baseColorTexture.index]; } let metallicRoughnessTexture = material.pbrMetallicRoughness.metallicRoughnessTexture; if (metallicRoughnessTexture !== void 0) { metallicRoughnessTexture.texture = gltfJson.textures[metallicRoughnessTexture.index]; } } let normalTexture = material.normalTexture; if (normalTexture !== void 0) { normalTexture.texture = gltfJson.textures[normalTexture.index]; } const occlusionTexture = material.occlusionTexture; if (occlusionTexture !== void 0) { occlusionTexture.texture = gltfJson.textures[occlusionTexture.index]; } const emissiveTexture = material.emissiveTexture; if (emissiveTexture !== void 0) { emissiveTexture.texture = gltfJson.textures[emissiveTexture.index]; } } } } _loadDependenciesOfTextures(gltfJson) { // Texture if (gltfJson.textures) { for (let texture of gltfJson.textures) { if (texture.sampler !== void 0) { texture.samplerIndex = texture.sampler; texture.sampler = gltfJson.samplers[texture.samplerIndex]; } if (texture.source !== void 0) { texture.sourceIndex = texture.source; texture.image = gltfJson.images[texture.sourceIndex]; } } } } _loadDependenciesOfJoints(gltfJson) { if (gltfJson.skins) { for (let skin of gltfJson.skins) { skin.skeletonIndex = skin.skeleton; skin.skeleton = gltfJson.nodes[skin.skeletonIndex]; skin.inverseBindMatricesIndex = skin.inverseBindMatrices; skin.inverseBindMatrices = gltfJson.accessors[skin.inverseBindMatricesIndex]; skin.jointsIndices = skin.joints; skin.joints = []; for (let jointIndex of skin.jointsIndices) { skin.joints.push(gltfJson.nodes[jointIndex]); } } } } _loadDependenciesOfAnimations(gltfJson) { if (gltfJson.animations) { for (let animation of gltfJson.animations) { for (let channel of animation.channels) { channel.samplerIndex = channel.sampler; channel.sampler = animation.samplers[channel.samplerIndex]; channel.target.nodeIndex = channel.target.node; channel.target.node = gltfJson.nodes[channel.target.nodeIndex]; } for (let channel of animation.channels) { channel.sampler.inputIndex = channel.sampler.input; channel.sampler.outputIndex = channel.sampler.output; channel.sampler.input = gltfJson.accessors[channel.sampler.inputIndex]; channel.sampler.output = gltfJson.accessors[channel.sampler.outputIndex]; if (channel.target.path === 'rotation') { if (channel.sampler.output.extras === void 0) { channel.sampler.output.extras = {}; } channel.sampler.output.extras.quaternionIfVec4 = true; } } } } } _loadDependenciesOfAccessors(gltfJson) { // Accessor for (let accessor of gltfJson.accessors) { if (accessor.bufferView !== void 0) { accessor.bufferViewIndex = accessor.bufferView; accessor.bufferView = gltfJson.bufferViews[accessor.bufferViewIndex]; } } } _loadDependenciesOfBufferViews(gltfJson) { // BufferView for (let bufferView of gltfJson.bufferViews) { if (bufferView.buffer !== void 0) { bufferView.bufferIndex = bufferView.buffer; bufferView.buffer = gltfJson.buffers[bufferView.bufferIndex]; } } } // _loadTransformationsOfNodes(gltfJson) { } _loadResources(arrayBufferBinary, basePath, gltfJson, options, resources) { let promisesToLoadResources = []; // Shaders Async load for (let i in gltfJson.shaders) { resources.shaders[i] = {}; let shaderJson = gltfJson.shaders[i]; let shaderType = shaderJson.type; if (typeof shaderJson.extensions !== 'undefined' && typeof shaderJson.extensions.KHR_binary_glTF !== 'undefined') { resources.shaders[i].shaderText = this._accessBinaryAsShader(shaderJson.extensions.KHR_binary_glTF.bufferView, gltfJson, arrayBufferBinary); resources.shaders[i].shaderType = shaderType; continue; } let shaderUri = shaderJson.uri; if (options.files) { const splitted = shaderUri.split('/'); const filename = splitted[splitted.length - 1]; if (options.files[filename]) { const arrayBuffer = options.files[filename]; shaders[shaderName].shaderText = DataUtil.arrayBufferToString(arrayBuffer); shaders[shaderName].shaderType = shaderType; continue; } } if (shaderUri.match(/^data:/)) { promisesToLoadResources.push( new Promise((resolve, rejected) => { let arrayBuffer = DataUtil.base64ToArrayBuffer(shaderUri); resources.shaders[i].shaderText = DataUtil.arrayBufferToString(arrayBuffer); resources.shaders[i].shaderType = shaderType; resolve(); }) ); } else { shaderUri = basePath + shaderUri; promisesToLoadResources.push( DataUtil.loadResourceAsync(shaderUri, false, (resolve, response)=>{ resources.shaders[i].shaderText = response; resources.shaders[i].shaderType = shaderType; resolve(gltfJson); }, (reject, error)=>{ } ) ); } } // Buffers Async load for (let i in gltfJson.buffers) { let bufferInfo = gltfJson.buffers[i]; let splitted = null; let filename = null; if (bufferInfo.uri) { splitted = bufferInfo.uri.split('/'); filename = splitted[splitted.length - 1]; } if (typeof bufferInfo.uri === 'undefined') { promisesToLoadResources.push( new Promise((resolve, rejected) => { resources.buffers[i] = arrayBufferBinary; bufferInfo.buffer = arrayBufferBinary; resolve(gltfJson); } )); } else if (bufferInfo.uri.match(/^data:application\/(.*);base64,/)) { promisesToLoadResources.push( new Promise((resolve, rejected) => { let arrayBuffer = DataUtil.base64ToArrayBuffer(bufferInfo.uri); resources.buffers[i] = arrayBuffer; bufferInfo.buffer = arrayBuffer; resolve(gltfJson); }) ); } else if (options.files && options.files[filename]) { promisesToLoadResources.push( new Promise((resolve, rejected) => { const arrayBuffer = options.files[filename]; resources.buffers[i] = arrayBuffer; bufferInfo.buffer = arrayBuffer; resolve(gltfJson); } )); } else { promisesToLoadResources.push( DataUtil.loadResourceAsync(basePath + bufferInfo.uri, true, (resolve, response)=>{ resources.buffers[i] = response; bufferInfo.buffer = response; resolve(gltfJson); }, (reject, error)=>{ } ) ); } } // Textures Async load for (let i in gltfJson.images) { let imageJson = gltfJson.images[i]; //let imageJson = gltfJson.images[textureJson.source]; //let samplerJson = gltfJson.samplers[textureJson.sampler]; let imageUri = null; if (typeof imageJson.uri === 'undefined') { imageUri = this._accessBinaryAsImage(imageJson.bufferView, gltfJson, arrayBufferBinary, imageJson.mimeType); } else { let imageFileStr = imageJson.uri; const splitted = imageFileStr.split('/'); const filename = splitted[splitted.length - 1]; if (options.files && options.files[filename]) { const arrayBuffer = options.files[filename]; const splitted = filename.split('.'); const fileExtension = splitted[splitted.length - 1]; imageUri = this._accessArrayBufferAsImage(arrayBuffer, fileExtension); } else if (imageFileStr.match(/^data:/)) { imageUri = imageFileStr; } else { imageUri = basePath + imageFileStr; } } if (options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (options.isTextureImageToLoadPreMultipliedAlpha) ; } else { // if is NOT Needed To Multiply AlphaToColor Of PixelOutput if (options.isTextureImageToLoadPreMultipliedAlpha) ; } // let texture = glBoostContext.createTexture(null, textureName, { // 'TEXTURE_MAG_FILTER': samplerJson.magFilter, // 'TEXTURE_MIN_FILTER': samplerJson.minFilter, // 'TEXTURE_WRAP_S': samplerJson.wrapS, // 'TEXTURE_WRAP_T': samplerJson.wrapT, // 'UNPACK_PREMULTIPLY_ALPHA_WEBGL': isNeededToMultiplyAlphaToColorOfTexture // }); if (options.extensionLoader && options.extensionLoader.setUVTransformToTexture) { options.extensionLoader.setUVTransformToTexture(texture, samplerJson); } promisesToLoadResources.push(new Promise((resolve, reject)=> { let img = new Image(); img.crossOrigin = 'Anonymous'; img.src = imageUri; imageJson.image = img; if (imageUri.match(/^data:/)) { resolve(gltfJson); } else { /* img.crossOrigin = 'Anonymous'; img.onload = () => { resolve(gltfJson); }; */ const load = (img, response)=> { var bytes = new Uint8Array(response); var binaryData = ""; for (var i = 0, len = bytes.byteLength; i < len; i++) { binaryData += String.fromCharCode(bytes[i]); } const split = imageUri.split('.'); let ext = split[split.length-1]; img.src = this._getImageType(ext) + window.btoa(binaryData); img.onload = ()=>{ resolve(gltfJson); }; /* var img = new Image(); img.crossOrigin = 'Anonymous'; var url = window.URL || window.webkitURL; img.src = url.createObjectURL(response); */ /* const split = imageUri.split('.'); let ext = split[split.length-1]; if (ext === 'jpg') { ext = 'jpeg'; } const blob = new Blob([ response ], { type: "image/"+ext }); *//* var reader = new FileReader(); reader.onloadend = ()=> { img.src = reader.result; resolve(gltfJson); } // DataURLとして読み込む reader.readAsDataURL(response); */ // resolve(gltfJson); }; const loadBinaryImage = ()=> { var xhr = new XMLHttpRequest(); //xhr.setRequestHeader('origin', 'x-requested-with'); xhr.onreadystatechange = (function(_img) { return function(){ //console.log('e2222222', this.readyState, this.status); if (this.readyState == 4 && this.status == 200) { /* var img = new Image(); var url = window.URL || window.webkitURL; img.src = url.createObjectURL(this.response); */ load(_img, this.response); } } })(img); xhr.open('GET', imageUri); xhr.responseType = 'arraybuffer'; xhr.send(); }; loadBinaryImage(); } resources.images[i] = img; })); } return Promise.all(promisesToLoadResources); } _sliceBufferViewToArrayBuffer(json, bufferViewStr, arrayBuffer) { let bufferViewJson = json.bufferViews[bufferViewStr]; let byteOffset = (bufferViewJson.byteOffset != null) ? bufferViewJson.byteOffset : 0; let byteLength = bufferViewJson.byteLength; let arrayBufferSliced = arrayBuffer.slice(byteOffset, byteOffset + byteLength); return arrayBufferSliced; } _accessBinaryAsImage(bufferViewStr, json, arrayBuffer, mimeType) { let arrayBufferSliced = this._sliceBufferViewToArrayBuffer(json, bufferViewStr, arrayBuffer); return this._accessArrayBufferAsImage(arrayBufferSliced, mimeType); } _getImageType(imageType) { let imgSrc = null; if (imageType === 'image/jpeg' || imageType.toLowerCase() === 'jpg' || imageType.toLowerCase() === 'jpeg') { imgSrc = "data:image/jpeg;base64,"; } else if (imageType == 'image/png' || imageType.toLowerCase() === 'png') { imgSrc = "data:image/png;base64,"; } else if (imageType == 'image/gif' || imageType.toLowerCase() === 'gif') { imgSrc = "data:image/gif;base64,"; } else if (imageType == 'image/bmp' || imageType.toLowerCase() === 'bmp') { imgSrc = "data:image/bmp;base64,"; } else { imgSrc = "data:image/unknown;base64,"; } return imgSrc; } _accessArrayBufferAsImage(arrayBuffer, imageType) { let bytes = new Uint8Array(arrayBuffer); let binaryData = ''; for (let i = 0, len = bytes.byteLength; i < len; i++) { binaryData += String.fromCharCode(bytes[i]); } let imgSrc = this._getImageType(imageType); let dataUrl = imgSrc + DataUtil.btoa(binaryData); return dataUrl; } } GLBoost$1["GLTF2Loader"] = GLTF2Loader; // let singleton$8 = Symbol(); let singletonEnforcer$5 = Symbol(); /** * */ class ModelConverter { /** * The constructor of GLTFLoader class. But you cannot use this constructor directly because of this class is a singleton class. Use getInstance() static method. * @param enforcer a Symbol to forbid calling this constructor directly */ constructor(enforcer ) { if (enforcer !== singletonEnforcer$5) { throw new Error("This is a Singleton class. get the instance using 'getInstance' static method."); } } /** * The static method to get singleton instance of this class. * @return The singleton instance of GLTFLoader class */ static getInstance() { if (!this[singleton$8]) { this[singleton$8] = new ModelConverter(singletonEnforcer$5); } return this[singleton$8]; } _getDefaultShader(options) { let defaultShader = null; if (options && typeof options.defaultShaderClass !== "undefined") { if (typeof options.defaultShaderClass === "string") { defaultShader = GLBoost$1[options.defaultShaderClass]; } else { defaultShader = options.defaultShaderClass; } } return defaultShader; } convertToGLBoostModel(glBoostContext, gltfModel) { // load binary data for (let accessor of gltfModel.accessors) { this._accessBinaryWithAccessor(accessor); } // Mesh data let glboostMeshes = this._setupMesh(glBoostContext, gltfModel); let groups = []; for (let node of gltfModel.nodes) { let group = glBoostContext.createGroup(); group.userFlavorName = node.name; groups.push(group); } // Transfrom this._setupTransform(gltfModel, groups); // Skeleton this._setupSkeleton(glBoostContext, gltfModel, groups, glboostMeshes); // Hierarchy this._setupHierarchy(glBoostContext, gltfModel, groups, glboostMeshes); // Animation this._setupAnimation(gltfModel, groups); // Root Group let rootGroup = glBoostContext.createGroup(); rootGroup.userFlavorName = 'FileRoot'; if (gltfModel.scenes[0].nodesIndices) { for (let nodesIndex of gltfModel.scenes[0].nodesIndices) { rootGroup.addChild(groups[nodesIndex], true); } } // Post Skeletal Proccess for (let glboostMesh of glboostMeshes) { if (glboostMesh instanceof M_SkeletalMesh) { if (!glboostMesh.jointsHierarchy) { glboostMesh.jointsHierarchy = rootGroup; } } } let options = gltfModel.asset.extras.glboostOptions; if (options.loaderExtension && options.loaderExtension.setAssetPropertiesToRootGroup) { options.loaderExtension.setAssetPropertiesToRootGroup(rootGroup, gltfModel.asset); } if (options && options.loaderExtension && options.loaderExtension.loadExtensionInfoAndSetToRootGroup) { options.loaderExtension.loadExtensionInfoAndSetToRootGroup(rootGroup, gltfModel, glBoostContext); } rootGroup.allMeshes = rootGroup.searchElementsByType(M_Mesh); return rootGroup; } _setupTransform(gltfModel, groups) { for (let node_i in gltfModel.nodes) { let group = groups[node_i]; let nodeJson = gltfModel.nodes[node_i]; if (nodeJson.translation) { group.translate = new Vector3(nodeJson.translation[0], nodeJson.translation[1], nodeJson.translation[2]); } if (nodeJson.scale) { group.scale = new Vector3(nodeJson.scale[0], nodeJson.scale[1], nodeJson.scale[2]); } if (nodeJson.rotation) { group.quaternion = new Quaternion(nodeJson.rotation[0], nodeJson.rotation[1], nodeJson.rotation[2], nodeJson.rotation[3]); } if (nodeJson.matrix) { group.matrix = new Matrix44$1(nodeJson.matrix, true); } } } _setupHierarchy(glBoostContext, gltfModel, groups, glboostMeshes) { for (let node_i in gltfModel.nodes) { let node = gltfModel.nodes[parseInt(node_i)]; let parentGroup = groups[node_i]; if (node.mesh) { parentGroup.addChild(glboostMeshes[node.meshIndex], true); } if (node.childrenIndices) { for (let childNode_i of node.childrenIndices) { let childGroup = groups[childNode_i]; parentGroup.addChild(childGroup, true); } } } } _setupAnimation(gltfModel, groups) { if (gltfModel.animations) { for (let animation of gltfModel.animations) { for (let channel of animation.channels) { let animInputArray = channel.sampler.input.extras.vertexAttributeArray; let animOutputArray = channel.sampler.output.extras.vertexAttributeArray; let animationAttributeName = ''; if (channel.target.path === 'translation') { animationAttributeName = 'translate'; } else if (channel.target.path === 'rotation') { animationAttributeName = 'quaternion'; } else { animationAttributeName = channel.target.path; } let group = groups[channel.target.nodeIndex]; if (group) { group.setAnimationAtLine('time', animationAttributeName, animInputArray, animOutputArray); group.setActiveAnimationLine('time'); } } } } } _setupSkeleton(glBoostContext, gltfModel, groups, glboostMeshes) { for (let node_i in gltfModel.nodes) { let node = gltfModel.nodes[node_i]; let group = groups[node_i]; if (node.skin && node.skin.skeleton) { group._isRootJointGroup = true; if (node.mesh) { let glboostMesh = glboostMeshes[node.meshIndex]; glboostMesh.jointsHierarchy = groups[node.skin.skeletonIndex]; } } if (node.skin && node.skin.joints) { for (let joint_i of node.skin.jointsIndices) { let joint = node.skin.joints[joint_i]; let options = gltfModel.asset.extras.glboostOptions; let glboostJoint = glBoostContext.createJoint(options.isExistJointGizmo); glboostJoint._glTFJointIndex = joint_i; let group = groups[joint_i]; group.addChild(glboostJoint, true); } } } } _setupMesh(glBoostContext, gltfModel) { let glboostMeshes = []; for (let mesh of gltfModel.meshes) { let geometry = null; let glboostMesh = null; if (mesh.extras && mesh.extras._skin && mesh.extras._skin.jointsIndices.length > 0) { geometry = glBoostContext.createSkeletalGeometry(); glboostMesh = glBoostContext.createSkeletalMesh(geometry, null); glboostMesh.gltfJointIndices = mesh.extras._skin.jointsIndices; if (mesh.extras._skin.inverseBindMatrices) { glboostMesh.inverseBindMatrices = mesh.extras._skin.inverseBindMatrices.extras.vertexAttributeArray; } else { glboostMesh.inverseBindMatrices = []; } } else { geometry = glBoostContext.createGeometry(); glboostMesh = glBoostContext.createMesh(geometry); } glboostMeshes.push(glboostMesh); let options = gltfModel.asset.extras.glboostOptions; if (options.isMeshTransparentAsDefault) { glboostMeshes.isTransparent = true; } let _indicesArray = []; let _positions = []; let _normals = []; let vertexData = { position: _positions, normal: _normals, components: {}, componentBytes: {}, componentType: {} }; let additional = { 'joint': [], 'weight': [], 'texcoord': [], 'color': [] }; let dataViewMethodDic = {}; let materials = []; let indicesAccumulatedLength = 0; let primitiveMode = 4; for (let i in mesh.primitives) { let primitive = mesh.primitives[i]; if (primitive.mode != null) { primitiveMode = primitive.mode; } { let accessor = primitive.attributes.POSITION; _positions[i] = accessor.extras.vertexAttributeArray; vertexData.components.position = accessor.extras.componentN; vertexData.componentBytes.position = accessor.extras.componentBytes; vertexData.componentType.position = accessor.componentType; dataViewMethodDic.position = accessor.extras.dataViewMethod; } let indices = null; if (typeof primitive.indices !== 'undefined') { primitive.indices.indices = gltfModel.accessors[primitive.indicesIndex]; indices = primitive.indices.indices.extras.vertexAttributeArray; for (let j=0; j 1) { let lengthDic = {index: 0, position: 0, normal: 0, joint: 0, weight: 0, texcoord: 0, color: 0}; for (let i = 0; i < mesh.primitives.length; i++) { //lengthDic.index += _indicesArray[i].length; lengthDic.position += _positions[i].length; if (_normals[i]) { lengthDic.normal += _normals[i].length; } if (typeof additional['joint'][i] !== 'undefined') { lengthDic.joint += additional['joint'][i].length; } if (typeof additional['weight'][i] !== 'undefined') { lengthDic.weight += additional['weight'][i].length; } if (typeof additional['texcoord'][i] !== 'undefined') { lengthDic.texcoord += additional['texcoord'][i].length; } if (typeof additional['color'][i] !== 'undefined') { lengthDic.color += additional['color'][i].length; } } function getTypedArray(dataViewMethod, length) { let vertexAttributeArray = null; if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(length); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(length); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = new Int16Array(length); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = new Uint16Array(length); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = new Int32Array(length); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = new Uint32Array(length); } else if (dataViewMethod === 'getFloat32') { vertexAttributeArray = new Float32Array(length); } return vertexAttributeArray; } for (let attribName in dataViewMethodDic) { let newTypedArray = getTypedArray(dataViewMethodDic[attribName], lengthDic[attribName]); let offset = 0; for (let i = 0; i < mesh.primitives.length; i++) { let array = null; if (attribName === 'position') { array = _positions[i]; } else if (attribName === 'normal') { array = _normals[i]; } else if (attribName === 'joint') { array = additional['joint'][i]; } else if (attribName === 'weight') { array = additional['weight'][i]; } else if (attribName === 'texcoord') { array = additional['texcoord'][i]; } else if (attribName === 'color') { array = additional['color'][i]; } if (array) { newTypedArray.set(array, offset); offset += array.length; } } if (attribName === 'position') { vertexData.position = newTypedArray; } else if (attribName === 'normal') { vertexData.normal = newTypedArray; } else if (attribName === 'joint') { additional['joint'] = newTypedArray; } else if (attribName === 'weight') { additional['weight'] = newTypedArray; } else if (attribName === 'texcoord') { additional['texcoord'] = newTypedArray; } else if (attribName === 'color') { additional['color'] = newTypedArray; } } } else { vertexData.position = _positions[0]; vertexData.normal = _normals[0]; additional['joint'] = additional['joint'][0]; additional['weight'] = additional['weight'][0]; additional['texcoord'] = additional['texcoord'][0]; additional['color'] = additional['color'][0]; } if (typeof vertexData.normal === 'undefined' || vertexData.normal.length === 0) { delete vertexData.normal; } if (typeof additional['joint'] === 'undefined' || additional['joint'].length === 0) { delete additional['joint']; } if (typeof additional['weight'] === 'undefined' || additional['weight'].length === 0) { delete additional['weight']; } if (typeof additional['texcoord'] === 'undefined' || additional['texcoord'].length === 0) { delete additional['texcoord']; } if (typeof additional['color'] === 'undefined' || additional['color'].length === 0) { delete additional['color']; } if (_indicesArray.length === 0) { _indicesArray = null; } geometry.setVerticesData(ArrayUtil.merge(vertexData, additional), _indicesArray, primitiveMode); geometry.materials = materials; } return glboostMeshes; } _setupMaterial(glBoostContext, gltfModel, gltfMaterial, materialJson, accessor, additional, vertexData, dataViewMethodDic, _positions, indices, geometry, i) { let options = gltfModel.asset.extras.glboostOptions; if (accessor) { additional['texcoord'][i] = accessor.extras.vertexAttributeArray; vertexData.components.texcoord = accessor.extras.componentN; vertexData.componentBytes.texcoord = accessor.extras.componentBytes; vertexData.componentType.texcoord = accessor.componentType; dataViewMethodDic.texcoord = accessor.extras.dataViewMethod; let setTextures = (materialJson)=> { if (materialJson.pbrMetallicRoughness) { let baseColorTexture = materialJson.pbrMetallicRoughness.baseColorTexture; if (baseColorTexture) { let sampler = baseColorTexture.texture.sampler; let isNeededToMultiplyAlphaToColorOfTexture = false; if (options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (options.isTextureImageToLoadPreMultipliedAlphaAsDefault) ; else { isNeededToMultiplyAlphaToColorOfTexture = true; } } else { // if is NOT Needed To Multiply AlphaToColor Of PixelOutput if (options.isTextureImageToLoadPreMultipliedAlphaAsDefault) ; } if (options && options.statesOfElements) { for (let statesInfo of options.statesOfElements) { if (statesInfo.targets) { for (let target of statesInfo.targets) { let isMatch = false; let specifyMethod = statesInfo.specifyMethod !== void 0 ? statesInfo.specifyMethod : GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME; switch (specifyMethod) { case GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME: isMatch = group.userFlavorName === target; break; case GLBoost$1.QUERY_TYPE_INSTANCE_NAME: isMatch = group.instanceName === target; break; case GLBoost$1.QUERY_TYPE_INSTANCE_NAME_WITH_USER_FLAVOR: isMatch = group.instanceNameWithUserFlavor === target; break; } if (isMatch) { if (options.isNeededToMultiplyAlphaToColorOfPixelOutput) { if (statesInfo.isTextureImageToLoadPreMultipliedAlpha) ; else { isNeededToMultiplyAlphaToColorOfTexture = true; } } else { // if is NOT Needed To Multiply AlphaToColor Of PixelOutput if (statesInfo.isTextureImageToLoadPreMultipliedAlpha) ; } } //texture.setParameter('UNPACK_PREMULTIPLY_ALPHA_WEBGL', isNeededToMultiplyAlphaToColorOfTexture); // texture.loadWebGLTexture(); } } } } let texture = glBoostContext.createTexture(baseColorTexture.texture.image.image, '', { 'TEXTURE_MAG_FILTER': sampler === void 0 ? GLBoost$1.LINEAR : sampler.magFilter, 'TEXTURE_MIN_FILTER': sampler === void 0 ? GLBoost$1.LINEAR_MIPMAP_LINEAR : sampler.minFilter, 'TEXTURE_WRAP_S': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapS, 'TEXTURE_WRAP_T': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapT, 'UNPACK_PREMULTIPLY_ALPHA_WEBGL': isNeededToMultiplyAlphaToColorOfTexture }); texture.userFlavorName = `Texture_Diffuse_index_${baseColorTexture.index}_of_${gltfMaterial.instanceNameWithUserFlavor}`; gltfMaterial.setTexture(texture, GLBoost$1.TEXTURE_PURPOSE_DIFFUSE); } let metallicRoughnessTexture = materialJson.pbrMetallicRoughness.metallicRoughnessTexture; if (metallicRoughnessTexture) { let sampler = metallicRoughnessTexture.texture.sampler; let texture = glBoostContext.createTexture(metallicRoughnessTexture.texture.image.image, '', { 'TEXTURE_MAG_FILTER': sampler === void 0 ? GLBoost$1.LINEAR : sampler.magFilter, 'TEXTURE_MIN_FILTER': sampler === void 0 ? GLBoost$1.LINEAR_MIPMAP_LINEAR : sampler.minFilter, 'TEXTURE_WRAP_S': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapS, 'TEXTURE_WRAP_T': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapT }); texture.userFlavorName = `Texture_MetallicRoughness_index_${metallicRoughnessTexture.index}_of_${gltfMaterial.instanceNameWithUserFlavor}`; gltfMaterial.setTexture(texture, GLBoost$1.TEXTURE_PURPOSE_METALLIC_ROUGHNESS); } const normalTexture = materialJson.normalTexture; if (normalTexture) { const sampler = normalTexture.texture.sampler; const texture = glBoostContext.createTexture(normalTexture.texture.image.image, '', { 'TEXTURE_MAG_FILTER': sampler === void 0 ? GLBoost$1.LINEAR : sampler.magFilter, 'TEXTURE_MIN_FILTER': sampler === void 0 ? GLBoost$1.LINEAR_MIPMAP_LINEAR : sampler.minFilter, 'TEXTURE_WRAP_S': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapS, 'TEXTURE_WRAP_T': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapT }); texture.userFlavorName = `Texture_MetallicRoughness_index_${normalTexture.index}_of_${gltfMaterial.instanceNameWithUserFlavor}`; gltfMaterial.setTexture(texture, GLBoost$1.TEXTURE_PURPOSE_NORMAL); } const occlusionTexture = materialJson.occlusionTexture; if (occlusionTexture) { const sampler = occlusionTexture.texture.sampler; const texture = glBoostContext.createTexture(occlusionTexture.texture.image.image, '', { 'TEXTURE_MAG_FILTER': sampler === void 0 ? GLBoost$1.LINEAR : sampler.magFilter, 'TEXTURE_MIN_FILTER': sampler === void 0 ? GLBoost$1.LINEAR_MIPMAP_LINEAR : sampler.minFilter, 'TEXTURE_WRAP_S': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapS, 'TEXTURE_WRAP_T': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapT }); texture.userFlavorName = `Texture_Occlusion_index_${occlusionTexture.index}_of_${gltfMaterial.instanceNameWithUserFlavor}`; gltfMaterial.setTexture(texture, GLBoost$1.TEXTURE_PURPOSE_OCCLUSION); } const emissiveTexture = materialJson.emissiveTexture; if (emissiveTexture) { const sampler = normalTexture.texture.sampler; const texture = glBoostContext.createTexture(emissiveTexture.texture.image.image, '', { 'TEXTURE_MAG_FILTER': sampler === void 0 ? GLBoost$1.LINEAR : sampler.magFilter, 'TEXTURE_MIN_FILTER': sampler === void 0 ? GLBoost$1.LINEAR_MIPMAP_LINEAR : sampler.minFilter, 'TEXTURE_WRAP_S': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapS, 'TEXTURE_WRAP_T': sampler === void 0 ? GLBoost$1.REPEAT : sampler.wrapT }); texture.userFlavorName = `Texture_Emissive_index_${emissiveTexture.index}_of_${gltfMaterial.instanceNameWithUserFlavor}`; gltfMaterial.setTexture(texture, GLBoost$1.TEXTURE_PURPOSE_EMISSIVE); } const alphaMode = materialJson.alphaMode; if (alphaMode === 'MASK') { // doalpha test in fragment shader gltfMaterial.isAlphaTest = true; gltfMaterial.alphaCutoff = materialJson.alphaCutoff; } let enables = []; if (options.isBlend || alphaMode === 'BLEND') { enables.push(3042); } if (options.isDepthTest) { enables.push(2929); } gltfMaterial.states.enable = enables; // It means, [gl.BLEND]; if (options.isBlend && options.isNeededToMultiplyAlphaToColorOfPixelOutput) { gltfMaterial.states.functions.blendFuncSeparate = [1, 771, 1, 771]; } gltfMaterial.globalStatesUsage = GLBoost$1.GLOBAL_STATES_USAGE_IGNORE; } }; setTextures(materialJson); } else { if (typeof vertexData.components.texcoord !== 'undefined') { // If texture coordinates existed even once in the previous loop let emptyTexcoords = []; let componentN = vertexData.components.position; let length = _positions[i].length / componentN; for (let k = 0; k < length; k++) { emptyTexcoords.push(0); emptyTexcoords.push(0); } additional['texcoord'][i] = new Float32Array(emptyTexcoords); vertexData.components.texcoord = 2; vertexData.componentBytes.texcoord = 4; dataViewMethodDic.texcoord = 'getFloat32'; } } const pmr = materialJson.pbrMetallicRoughness; if (pmr != null) { if (pmr.baseColorFactor) { gltfMaterial.baseColor = new Vector4$1(pmr.baseColorFactor); } if (pmr.metallicFactor) { gltfMaterial.metallic = pmr.metallicFactor; } if (pmr.roughnessFactor) { gltfMaterial.roughness = pmr.roughnessFactor; } if (materialJson.emissiveFactor) { gltfMaterial.emissive = new Vector3(materialJson.emissiveFactor); } } if (indices !== null) { gltfMaterial.setVertexN(geometry, indices.length); } const defaultShader = this._getDefaultShader(options); if (defaultShader) { gltfMaterial.shaderClass = defaultShader; } } _adjustByteAlign(typedArrayClass, arrayBuffer, alignSize, byteOffset, length) { if (( byteOffset % alignSize ) != 0) { return new typedArrayClass(arrayBuffer.slice(byteOffset), 0, length); } else { return new typedArrayClass(arrayBuffer, byteOffset, length); } } _checkBytesPerComponent(accessor) { var bytesPerComponent = 0; switch (accessor.componentType) { case 5120: // gl.BYTE bytesPerComponent = 1; break; case 5121: // gl.UNSIGNED_BYTE bytesPerComponent = 1; break; case 5122: // gl.SHORT bytesPerComponent = 2; break; case 5123: // gl.UNSIGNED_SHORT bytesPerComponent = 2; break; case 5124: // gl.INT bytesPerComponent = 4; break; case 5125: // gl.UNSIGNED_INT bytesPerComponent = 4; break; case 5126: // gl.FLOAT bytesPerComponent = 4; break; default: break; } return bytesPerComponent; } _checkComponentNumber(accessor) { var componentN = 0; switch (accessor.type) { case 'SCALAR': componentN = 1; break; case 'VEC2': componentN = 2; break; case 'VEC3': componentN = 3; break; case 'VEC4': componentN = 4; break; case 'MAT4': componentN = 16; break; } return componentN; } _checkDataViewMethod(accessor) { var dataViewMethod = ''; switch (accessor.componentType) { case 5120: // gl.BYTE dataViewMethod = 'getInt8'; break; case 5121: // gl.UNSIGNED_BYTE dataViewMethod = 'getUint8'; break; case 5122: // gl.SHORT dataViewMethod = 'getInt16'; break; case 5123: // gl.UNSIGNED_SHORT dataViewMethod = 'getUint16'; break; case 5124: // gl.INT dataViewMethod = 'getInt32'; break; case 5125: // gl.UNSIGNED_INT dataViewMethod = 'getUint32'; break; case 5126: // gl.FLOAT dataViewMethod = 'getFloat32'; break; default: break; } return dataViewMethod; } static _isSystemLittleEndian() { return !!(new Uint8Array((new Uint16Array([0x00ff])).buffer))[0]; } _accessBinaryWithAccessor(accessor) { var bufferView = accessor.bufferView; const byteOffset = bufferView.byteOffset + (accessor.byteOffset !== void 0 ? accessor.byteOffset : 0); var buffer = bufferView.buffer; var arrayBuffer = buffer.buffer; let componentN = this._checkComponentNumber(accessor); let componentBytes = this._checkBytesPerComponent(accessor); let dataViewMethod = this._checkDataViewMethod(accessor); if (accessor.extras === void 0) { accessor.extras = {}; } accessor.extras.componentN = componentN; accessor.extras.componentBytes = componentBytes; accessor.extras.dataViewMethod = dataViewMethod; var byteLength = componentBytes * componentN * accessor.count; var vertexAttributeArray = []; if (accessor.extras && accessor.extras.toGetAsTypedArray) { if (ModelConverter._isSystemLittleEndian()) { if (dataViewMethod === 'getFloat32') { vertexAttributeArray = this._adjustByteAlign(Float32Array, arrayBuffer, 4, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(arrayBuffer, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(arrayBuffer, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = this._adjustByteAlign(Int16Array, arrayBuffer, 2, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = this._adjustByteAlign(Uint16Array, arrayBuffer, 2, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = this._adjustByteAlign(Int32Array, arrayBuffer, 4, byteOffset, byteLength / componentBytes); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = this._adjustByteAlign(Uint32Array, arrayBuffer, 4, byteOffset, byteLength / componentBytes); } } else { let dataView = new DataView(arrayBuffer, byteOffset, byteLength); let byteDelta = componentBytes * componentN; let littleEndian = true; for (let pos = 0; pos < byteLength; pos += byteDelta) { switch (accessor.type) { case 'SCALAR': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); break; case 'VEC2': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes, littleEndian)); break; case 'VEC3': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes * 2, littleEndian)); break; case 'VEC4': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes * 2, littleEndian)); vertexAttributeArray.push(dataView[dataViewMethod](pos + componentBytes * 3, littleEndian)); break; } } if (dataViewMethod === 'getInt8') { vertexAttributeArray = new Int8Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint8') { vertexAttributeArray = new Uint8Array(vertexAttributeArray); } else if (dataViewMethod === 'getInt16') { vertexAttributeArray = new Int16Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint16') { vertexAttributeArray = new Uint16Array(vertexAttributeArray); } else if (dataViewMethod === 'getInt32') { vertexAttributeArray = new Int32Array(vertexAttributeArray); } else if (dataViewMethod === 'getUint32') { vertexAttributeArray = new Uint32Array(vertexAttributeArray); } else if (dataViewMethod === 'getFloat32') { vertexAttributeArray = new Float32Array(vertexAttributeArray); } } } else { let dataView = new DataView(arrayBuffer, byteOffset, byteLength); let byteDelta = componentBytes * componentN; let littleEndian = true; for (let pos = 0; pos < byteLength; pos += byteDelta) { switch (accessor.type) { case 'SCALAR': vertexAttributeArray.push(dataView[dataViewMethod](pos, littleEndian)); break; case 'VEC2': vertexAttributeArray.push(new Vector2( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+componentBytes, littleEndian) )); break; case 'VEC3': vertexAttributeArray.push(new Vector3( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+componentBytes, littleEndian), dataView[dataViewMethod](pos+componentBytes*2, littleEndian) )); break; case 'VEC4': if (accessor.extras && accessor.extras.quaternionIfVec4) { vertexAttributeArray.push(new Quaternion( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+componentBytes, littleEndian), dataView[dataViewMethod](pos+componentBytes*2, littleEndian), dataView[dataViewMethod](pos+componentBytes*3, littleEndian) )); } else { vertexAttributeArray.push(new Vector4$1( dataView[dataViewMethod](pos, littleEndian), dataView[dataViewMethod](pos+componentBytes, littleEndian), dataView[dataViewMethod](pos+componentBytes*2, littleEndian), dataView[dataViewMethod](pos+componentBytes*3, littleEndian) )); } break; case 'MAT4': let matrixComponents = []; for (let i=0; i<16; i++) { matrixComponents[i] = dataView[dataViewMethod](pos+componentBytes*i, littleEndian); } vertexAttributeArray.push(new Matrix44$1(matrixComponents, true)); break; } } } accessor.extras.vertexAttributeArray = vertexAttributeArray; return vertexAttributeArray; } } GLBoost$1["ModelConverter"] = ModelConverter; if (typeof phina !== 'undefined') { phina.namespace(function() { /** * @class */ phina.define('phina.display.GLBoostLayer', { superClass: 'phina.display.Layer', scene: null, expression: null, camera: null, light: null, glBoostContext: null, renderer: null, canvas: null, /** rendering child by self CanvasRenderer or not */ renderChildBySelf: true, init: function(params) { this.superInit(params); this.originX = 0; this.originY = 0; this.canvas = document.createElement("canvas"); this.canvas.id = 'glboost_world'; this.canvas.width = params.width; this.canvas.height = params.height; var bodyElm = document.getElementsByTagName("body").item(0); bodyElm.appendChild(this.canvas); this.canvas.style.display = "none"; this.glBoostContext = new GLBoostMiddleContext(this.canvas); // create renderer this.renderer = this.glBoostContext.createRenderer({clearColor: {red:1, green:1, blue:1, alpha:1}}); this.scene = this.glBoostContext.createScene(); this.expression = this.glBoostContext.createExpressionAndRenderPasses(1); this.expression.renderPasses[0].scene = this.scene; this.on('enterframe', function() { if (this.scene) { this.renderer.clearCanvas(); this.renderer.draw(this.expression); } }); this.domElement = this.canvas; } }); phina.define("phina.display.OffScreenLayer", { superClass: 'phina.display.Layer', /** * rendering child by self CanvasRenderer or not */ renderChildBySelf: true, /** For drawing child attribute canvas */ canvas2d: null, /** To drawing canvas2d renderer */ renderer2d: null, width: 0, height: 0, init: function (params) { this.superInit(); this.width = params.width; this.height = params.height; if (params.fillStyle instanceof Vector3) { this.fillStyle = `rgb(${params.fillStyle.x * 255},${params.fillStyle.y * 255},${params.fillStyle.z * 255},1)`; } else if (params.fillStyle instanceof Vector4$1) { this.fillStyle = `rgba(${params.fillStyle.x * 255},${params.fillStyle.y * 255},${params.fillStyle.z * 255},${params.fillStyle.w})`; } else { this.fillStyle = params.fillStyle; } this.canvas2d = phina.graphics.Canvas(); this.canvas2d.setSize(this.width, this.height); this.renderer2d = phina.display.CanvasRenderer(this.canvas2d); }, reset: function() { this.canvas2d.clearColor('white', 0, 0, this.width, this.height); this.canvas2d.clearColor(this.fillStyle, 0, 0, this.width, this.height); // this.canvas2d.clear(0, 0, this.width, this.height); /* this.canvas2d.init(); this.canvas2d.setSize(this.width, this.height); this.renderer2d = phina.display.CanvasRenderer(this.canvas2d); */ }, renderObject: function(obj) { var layer = DisplayElement(); obj.flare('enterframe'); obj.addChildTo(layer); this.renderer2d.renderObject(layer); }, getImageDataURL: function() { return this.canvas2d.domElement.toDataURL('image/png'); } }); }); } class BlinnPhongShaderSource { FSDefine_BlinnPhongShaderSource(in_, f, lights) { var shaderText = ''; shaderText += `uniform vec3 viewPosition;\n`; shaderText += `uniform vec4 Kd;\n`; shaderText += `uniform vec4 Ks;\n`; shaderText += `uniform float power;\n`; shaderText += 'uniform vec4 ambient;\n'; // Ka * amount of ambient lights var sampler2D = this._sampler2DShadow_func(); let lightNumExceptAmbient = lights.filter((light)=>{return !light.isTypeAmbient();}).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_BlinnPhongShaderSource(f, gl, lights) { var shaderText = ''; shaderText += ' float depthBias = 0.005;\n'; shaderText += ' vec4 surfaceColor = rt0;\n'; shaderText += ' rt0 = vec4(0.0, 0.0, 0.0, 0.0);\n'; for (let i=0; i{return !light.isTypeAmbient();}).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_HalfLambertShaderSource(f, gl, lights) { var shaderText = ''; shaderText += ' vec4 surfaceColor = rt0;\n'; shaderText += ' rt0 = vec4(0.0, 0.0, 0.0, 0.0);\n'; for (let i=0; i{return !light.isTypeAmbient();}).length; if (lightNumExceptAmbient > 0) { shaderText += `uniform highp ${sampler2D} uDepthTexture[${lightNumExceptAmbient}];\n`; shaderText += `${in_} vec4 v_shadowCoord[${lightNumExceptAmbient}];\n`; shaderText += `uniform int isShadowCasting[${lightNumExceptAmbient}];\n`; } return shaderText; } FSShade_HalfLambertAndWrapLightingShaderSource(f, gl, lights) { var shaderText = ''; shaderText += ' vec4 surfaceColor = rt0;\n'; shaderText += ' rt0 = vec4(0.0, 0.0, 0.0, 0.0);\n'; for (let i=0; i{ if (attribName === 'position' || attribName === 'normal' || attribName === 'tangent') { shaderProgram['vertexAttribute_' + attribName] = gl.getAttribLocation(shaderProgram, 'aVertex_' + attribName); if (shaderProgram['vertexAttribute_' + attribName] !== -1) { gl.enableVertexAttribArray(shaderProgram['vertexAttribute_' + attribName]); vertexAttribsAsResult.push(attribName); } } }); material.setUniform(shaderProgram, 'uniform_worldMatrix', this._glContext.getUniformLocation(shaderProgram, 'worldMatrix')); material._semanticsDic['WORLD'] = 'worldMatrix'; if (existCamera_f) { material.setUniform(shaderProgram, 'uniform_viewMatrix', this._glContext.getUniformLocation(shaderProgram, 'viewMatrix')); material._semanticsDic['VIEW'] = 'viewMatrix'; material.setUniform(shaderProgram, 'uniform_projectionMatrix', this._glContext.getUniformLocation(shaderProgram, 'projectionMatrix')); material._semanticsDic['PROJECTION'] = 'projectionMatrix'; } material.registerTextureUnitToUniform(GLBoost$1.TEXTURE_PURPOSE_ENV_CUBE, shaderProgram, 'uEnvTexture'); return vertexAttribsAsResult; } } class EnvironmentMapShader extends Shader { constructor(glBoostContext) { super(glBoostContext); EnvironmentMapShader.mixin(EnvironmentMapShaderSource); } setUniforms(gl, glslProgram, scene, material, camera, mesh, lights) { super.setUniforms(gl, glslProgram, scene, material, camera, mesh, lights); material.updateTextureInfo(GLBoost$1.TEXTURE_PURPOSE_ENV_CUBE, 'uEnvTexture'); } setUniformsAsTearDown(gl, glslProgram, scene, material, camera, mesh, lights) { super.setUniformsAsTearDown(gl, glslProgram, scene, material, camera, mesh, lights); } } GLBoost$1['EnvironmentMapShader'] = EnvironmentMapShader; class JointGizmoUpdater { static update() { } } if (GLBoost['JointGizmoUpdater'] === void 0) { GLBoost['JointGizmoUpdater'] = JointGizmoUpdater; } // let singleton$9 = Symbol(); let singletonEnforcer$6 = Symbol(); /** * This is a loader class of glTF VRize extension Data. */ class GLBoostGLTFLoaderExtension { /** * The constructor of ObjLoader class. But you cannot use this constructor directly because of this class is a singleton class. Use getInstance() static method. * @param enforcer a Symbol to forbid calling this constructor directly */ constructor(enforcer ) { if (enforcer !== singletonEnforcer$6) { throw new Error("This is a Singleton class. get the instance using 'getInstance' static method."); } } /** * The static method to get singleton instance of this class. * @return the singleton instance of ObjLoader class */ static getInstance() { if (!this[singleton$9]) { this[singleton$9] = new GLBoostGLTFLoaderExtension(singletonEnforcer$6); } return this[singleton$9]; } setUVTransformToTexture(texture, samplerJson) { let uvTransform = new Vector4$1(1, 1, 0, 0); if (samplerJson.extras && samplerJson.extras.scale) { let scale = samplerJson.extras.scale; uvTransform.x = scale[0]; uvTransform.y = scale[1]; } if (samplerJson.extras && samplerJson.extras.translation) { let translation = samplerJson.extras.translation; uvTransform.z = translation[0]; uvTransform.w = translation[1]; } texture.uvTransform = uvTransform; } setAssetPropertiesToRootGroup(rootGroup, asset) { // Animation FPS if (asset && asset.animationFps) { rootGroup.animationFps = asset.animationFps; } // other information if (asset && asset.version) { rootGroup.version = asset.version; } if (asset && asset.LastSaved_ApplicationVendor) { rootGroup.LastSaved_ApplicationVendor = asset.LastSaved_ApplicationVendor; } if (asset && asset.LastSaved_ApplicationName) { rootGroup.LastSaved_ApplicationName = asset.LastSaved_ApplicationName; } if (asset && asset.LastSaved_ApplicationVersion) { rootGroup.LastSaved_ApplicationVersion = asset.LastSaved_ApplicationVersion; } // Animation Tracks if (asset && asset.extras && asset.extras.animation_tracks) { rootGroup.animationTracks = asset.extras.animation_tracks; } // Transparent Meshes Draw Order if (asset && asset.extras) { const transparentMeshesAsManualOrder = (asset.extras.transparent_meshes_draw_order != null) ? asset.extras.transparent_meshes_draw_order : []; let meshParents = rootGroup.searchElementsByType(M_Group); const transparentMeshes = []; for (let name of transparentMeshesAsManualOrder) { for (let parent of meshParents) { if (parent.userFlavorName === name) { const mesh = parent.getChildren()[0]; if (mesh.isTransparent) { transparentMeshes.push(mesh); } break; } } } rootGroup.transparentMeshesAsManualOrder = transparentMeshes; } } loadExtensionInfoAndSetToRootGroup(rootGroup, json, glBoostContext) { rootGroup['extensions'] = json.extensions; if (json.extensions && json.extensions.GLBoost) { const ext = json.extensions.GLBoost; // Assignment for Backward Compatibility if (ext.animation) { if (ext.animation.fps != null) { rootGroup.animationFps = ext.animation.fps; } if (ext.animation.tracks != null) { rootGroup.animationTracks = ext.animation.tracks; } } const transparentMeshesDrawOrder = ext.transparentMeshesDrawOrder; if (transparentMeshesDrawOrder) { let meshParents = rootGroup.searchElementsByType(M_Group); const transparentMeshes = []; for (let name of transparentMeshesDrawOrder) { for (let parent of meshParents) { if (parent.userFlavorName === name) { const mesh = parent.getChildren()[0]; if (mesh.isTransparent) { transparentMeshes.push(mesh); } break; } } } rootGroup.transparentMeshesAsManualOrder = transparentMeshes; } } if (json.extensions && json.extensions.Effekseer) { const ext = json.extensions.Effekseer; for (let effect of ext.effects) { const group = rootGroup.searchElement(effect.nodeName, {type: GLBoost$1.QUERY_TYPE_USER_FLAVOR_NAME, format:GLBoost$1.QUERY_FORMAT_STRING_PERFECT_MATCHING}); const effekseerElm = glBoostContext.createEffekseerElement(); const promise = effekseerElm.load(asset.extras.basePath + effect.efkName + '.efk', true, true); promise.then((effect)=>{ group.addChild(effect); }); } } } } GLBoost$1["GLBoostGLTFLoaderExtension"] = GLBoostGLTFLoaderExtension; /* */ class AnimationPlayer { constructor() { } init(group ) { this.__FpsForPlaying = (group.animationFps !== void 0) ? group.animationFps:60; this.__animationStartTime = group.getStartAnimationInputValue('time'); this.__animationEndTime = group.getEndAnimationInputValue('time'); this.__animationStartRange = this.__animationStartTime; this.__animationEndRange = this.__animationEndTime; this.__animationCurrentTime = this.__animationStartTime; this.__animationLength = group.getEndAnimationInputValue('time'); this.__animationLastTime = 0; this.__currentMillisecondAtStart = 0; this.__isPlaying = false; this.__currentMotion = "All"; this.__animationMotions = []; this.__setupMultiMotions(group); } play() { this.__isPlaying = true; this.__currentMillisecondAtStart = Date.now(); } calcAnimationTime(speedRatio = 1) { if (!this.__isPlaying) { this.__currentMillisecondAtStart = Date.now(); return this.__animationCurrentTime; } let currentMillisecondFromStart = Date.now(); this.__animationCurrentTime = (currentMillisecondFromStart - this.__currentMillisecondAtStart)/1000 + this.__animationLastTime; let localAnimationCurrentTime = this.__animationCurrentTime * speedRatio; if (localAnimationCurrentTime > this.__animationEndRange) { this.moveToTheTime(this.__animationStartRange); } else if (localAnimationCurrentTime < this.__animationStartRange) { this.moveToTheTime(this.__animationStartRange); } if (this.__animationStartRange > this.__animationLength) { this.moveToTheTime(this.__animationStartRange); } this.__animationCurrentTime = localAnimationCurrentTime / speedRatio; return localAnimationCurrentTime; } __setupMultiMotions(group ) { const json = { "name": "All", "start": group.getStartAnimationInputValue('time') * this.__FpsForPlaying, "end": group.getEndAnimationInputValue('time') * this.__FpsForPlaying }; this.animationMotions.push(json); if (!group.animationTracks) { return; } if (group.animationTracks) { Array.prototype.push.apply(this.animationMotions, group.animationTracks); } this.__currentMotion = group.animationTracks[0].name; } moveToTheTime(time ) { this.__currentMillisecondAtStart = Date.now(); this.__animationCurrentTime = time; this.__animationLastTime = this.__animationCurrentTime; } changeMotion(motionName ) { for(let motion of this.__animationMotions) { if (motion.name === motionName) { this.changeRange(motion.start / this.__FpsForPlaying, motion.end / this.__FpsForPlaying); this.moveToTheTime(motion.start / this.__FpsForPlaying); } } } changeRange(start , end ) { this.__animationStartRange = start; this.__animationEndRange = end; const time = this.__animationCurrentTime; this.moveToTheTime(time); }; get animationMotions() { return this.__animationMotions; } set animationMotions(motions ) { this.__animationMotions = motions; } } GLBoost$1['AnimationPlayer'] = AnimationPlayer; async function formatDetector(uri, files) { if (files) { for (let fileName in files) { const splitted = fileName.split('.'); const fileExtension = splitted[splitted.length - 1]; if (fileExtension === 'gltf' || fileExtension === 'glb') { return new Promise((resolve, reject)=>{ checkArrayBufferOfGltf(files[fileName], resolve); }); } } } const splitted = uri.split('.'); const fileExtension = splitted[splitted.length - 1]; // Effekseer if (fileExtension === 'efk') { return new Promise((resolve, reject)=>{ resolve('Effekseer'); }); } // glTF return DataUtil.loadResourceAsync(uri, true, (resolve, response)=> { const arrayBuffer = response; checkArrayBufferOfGltf(arrayBuffer, resolve); } ); } function checkArrayBufferOfGltf(arrayBuffer, resolve) { const isLittleEndian = true; const dataView = new DataView(arrayBuffer, 0, 20); // Magic field const magic = dataView.getUint32(0, isLittleEndian); // 0x46546C67 is 'glTF' in ASCII codes. if (magic !== 0x46546C67) { // It must be normal glTF (NOT binary) file... let gotText = DataUtil.arrayBufferToString(arrayBuffer); let gltfJson = JSON.parse(gotText); let glTFVer = checkGLTFVersion(gltfJson); resolve("glTF"+glTFVer); return; } let glTFVer = dataView.getUint32(4, isLittleEndian); resolve("glTF"+glTFVer); } function checkGLTFVersion(gltfJson) { let glTFVer = 1.0; if (gltfJson.asset && gltfJson.asset.version) { glTFVer = parseFloat(gltfJson.asset.version); } return glTFVer; } GLBoost$1["formatDetector"] = formatDetector; }))); (0,eval)('this').GLBoost.VERSION='version: 0.0.4-388-gd606-mod branch: develop';