11// MMD for System Animator
2- // (2024-12-15 )
2+ // (2024-12-29 )
33
44var use_full_spectrum = true
55
@@ -9165,7 +9165,7 @@ if (!MMD_SA.MMD_started)
91659165 get: ()=>{ return bone_map_MMD_to_VRM; }
91669166 },
91679167
9168- get_bone_by_MMD_name : {
9168+ get_bone_by_MMD_name: {
91699169 value: function (name) {
91709170name = bone_map_MMD_to_VRM[name];
91719171return (!name) ? null : this.getBoneNode(name);
@@ -10425,10 +10425,13 @@ System._browser.on_animation_update.add(()=>{
1042510425
1042610426 threeX.scene.add(model_new.model.scene);
1042710427
10428- const canvas = MMD_SA_options.Dungeon.character.icon;
10429- const ctx = canvas.getContext("2d");
10430- ctx.drawImage((model_new.is_VRM1)?model_new.model.meta.thumbnailImage:model_new.model.meta.texture.source.data, 0,0,64,64);
10431- MMD_SA_options.Dungeon.update_status_bar(true);
10428+ const icon = (model_new.is_VRM1) ? model_new.model.meta.thumbnailImage : model_new.model.meta.texture?.source.data;
10429+ if (icon) {
10430+ const canvas = MMD_SA_options.Dungeon.character.icon;
10431+ const ctx = canvas.getContext("2d");
10432+ ctx.drawImage(icon, 0,0,64,64);
10433+ MMD_SA_options.Dungeon.update_status_bar(true);
10434+ }
1043210435
1043310436 MMD_SA._force_motion_shuffle = true;
1043410437
@@ -14227,6 +14230,139 @@ obj.traverse(node => {
1422714230console.log('geo_disposed:' + geo_disposed, 'map_disposed:' + map_disposed, 'mtrl_disposed:' + mtrl_disposed, 'misc_disposed:' + misc_disposed);
1422814231 },
1422914232
14233+ display_helper: (()=>{
14234+ const helpers = {};
14235+
14236+ let position, quaternion, scale, matrixWorld;
14237+ let _q1, _e1;
14238+ window.addEventListener('jThree_ready', ()=>{
14239+ position = new THREE.Vector3();
14240+ quaternion = new THREE.Quaternion();
14241+ scale = new THREE.Vector3();
14242+ matrixWorld = new THREE.Matrix4();
14243+
14244+ _q1 = new THREE.Quaternion();
14245+ _e1 = new THREE.Euler();
14246+ });
14247+
14248+ window.addEventListener('SA_MMD_before_render', ()=>{
14249+ for (const id in helpers) {
14250+ const helper_para = helpers[id];
14251+ const helper = helper_para.obj;
14252+ if (RAF_timestamp < helper_para.timestamp_ini + helper_para.duration) {
14253+ let helper_parent = helper_para.parent;
14254+ if (typeof helper_parent == 'string') {
14255+ const modelX = threeX.get_model(0);
14256+ const is_MMD_dummy = (modelX.type=='MMD_dummy');
14257+
14258+ const bone = modelX.get_bone_by_MMD_name(VRM.bone_map_VRM_to_MMD[helper_parent]);
14259+ const bone_matrix = (is_MMD_dummy) ? bone.skinMatrix : bone.matrixWorld;
14260+
14261+ position.setFromMatrixPosition(bone_matrix);
14262+ quaternion.setFromRotationMatrix(matrixWorld.extractRotation(bone_matrix));
14263+
14264+ // multiply, instead of premultiply
14265+ if (!is_MMD_dummy && !modelX.is_VRM1) quaternion.multiply(_q1.set(0,-1,0,0));
14266+
14267+ if (is_MMD_dummy) {
14268+ position.applyQuaternion(modelX.mesh.quaternion).add(modelX.mesh.position);
14269+ quaternion.premultiply(modelX.mesh.quaternion);
14270+ }
14271+
14272+ matrixWorld.compose(position, quaternion, scale.set(1,1,1));
14273+ }
14274+ else {
14275+ matrixWorld.copy(helper_parent.matrixWorld).decompose(position, quaternion, scale);
14276+ }
14277+
14278+ if (!helper_para.use_parent_scale)
14279+ helper.scale.set(1/scale.x, 1/scale.y, 1/scale.z);
14280+ helper.updateMatrix();
14281+
14282+ helper.matrixWorld.multiplyMatrices( matrixWorld, helper.matrix );
14283+ helper.matrix.copy(helper.matrixWorld);
14284+
14285+ helper.visible = true;
14286+ }
14287+ else {
14288+ helper.visible = false;
14289+ }
14290+ }
14291+ });
14292+
14293+ return function (helper_id, helper_parent, para) {
14294+ let helper;
14295+ let helper_para = helpers[helper_id];
14296+ if (!helper_para) {
14297+ helper_para = helpers[helper_id] = {};
14298+
14299+ const THREE = threeX.THREE;
14300+ if (para.type == 'plane') {
14301+ helper = helper_para.obj = new THREE.GridHelper(3, 30, '#ff8', '#ff8');
14302+ }
14303+ else if (para.type == 'line') {
14304+ const material = new THREE.LineBasicMaterial({ color:'#8ff' });
14305+
14306+ let geometry;
14307+ if (threeX.enabled) {
14308+ geometry = new THREE.BufferGeometry().setFromPoints( para.line.map(p=>new THREE.Vector3().copy(p)) );
14309+ }
14310+ else {
14311+ geometry = new THREE.Geometry();
14312+ geometry.vertices.push(...para.line.map(p=>new THREE.Vector3().copy(p)));
14313+ }
14314+
14315+ helper = helper_para.obj = new THREE.Line( geometry, material );
14316+
14317+ helper_para.use_parent_scale = true;
14318+ }
14319+ else {
14320+ helper = helper_para.obj = new THREE[(threeX.enabled)?'AxesHelper':'AxisHelper'](1);
14321+ }
14322+
14323+ helper.matrixAutoUpdate = false;
14324+ if (threeX.enabled)
14325+ helper.renderOrder = 99;
14326+ helper.material.depthTest = false;
14327+
14328+ threeX.scene.add(helper);
14329+ }
14330+ else {
14331+ helper = helper_para.obj;
14332+ if (para.type == 'line') {
14333+ if (threeX.enabled) {
14334+ const pos = helper.geometry.getAttribute('position');
14335+ para.line.forEach((v,i)=>{
14336+ pos.array[i*3+0] = v.x;
14337+ pos.array[i*3+1] = v.y;
14338+ pos.array[i*3+2] = v.z;
14339+ });
14340+ pos.needsUpdate = true;
14341+ }
14342+ else {
14343+ const geometry = helper.geometry;
14344+ geometry.vertices.forEach((v,i)=>{
14345+ v.copy(para.line[i]);
14346+ });
14347+ geometry.verticesNeedUpdate = true;
14348+ }
14349+ }
14350+ }
14351+
14352+ helper_para.parent = helper_parent;
14353+ helper_para.timestamp_ini = RAF_timestamp;
14354+ helper_para.duration = 5000;
14355+
14356+ if (para.pos)
14357+ helper.position.set(para.pos.x, para.pos.y, para.pos.z);
14358+
14359+ if (para.rot) {
14360+ d2r = Math.PI/180;
14361+ helper.quaternion.copy(quaternion.setFromEuler(_e1.set(para.rot.x*d2r, para.rot.y*d2r, para.rot.z*d2r)));
14362+ }
14363+ };
14364+ })(),
14365+
1423014366// headless_mode
1423114367 press_key: function (k) {
1423214368const ck = k.split('+');
@@ -15131,7 +15267,7 @@ if (v) {
1513115267
1513215268 depth_effect: depth_effect,
1513315269
15134- generate_mesh: function (use_depth_transform_shader=MMD_SA.THREEX.enabled) {
15270+ generate_mesh: function (use_depth_transform_shader=true) {// MMD_SA.THREEX.enabled) {
1513515271const THREE = MMD_SA.THREEX.THREE;
1513615272
1513715273const geometry = new THREE.PlaneGeometry(1,1, (this.depth_dim-1),(this.depth_dim-1));
@@ -15141,15 +15277,17 @@ if (!use_depth_transform_shader) {
1514115277 material = new THREE.MeshBasicMaterial( { map:this.texture, fog:false } );
1514215278}
1514315279else {
15144- vertexShader = THREE.ShaderLib.basic.vertexShader.replace(
15280+ let vertexShader;
15281+ if (MMD_SA.THREEX.enabled) {
15282+ vertexShader = THREE.ShaderLib.basic.vertexShader.replace(
1514515283'void main() {',
1514615284[
1514715285 'uniform sampler2D Wallpaper3D_displacementMap;',
1514815286 'uniform float Wallpaper3D_camera_factor;',
1514915287 'uniform float Wallpaper3D_camera_distance_offset;',
1515015288 'uniform float Wallpaper3D_scale_z;',
1515115289 'uniform vec3 Wallpaper3D_pos_offset;',
15152- 'uniform mat4 Wallpaper3D_modelViewMatrix;',
15290+ // 'uniform mat4 Wallpaper3D_modelViewMatrix;',
1515315291
1515415292 'void main() {',
1515515293].join('\n')
@@ -15164,9 +15302,11 @@ else {
1516415302
1516515303 '#include <project_vertex>',
1516615304].join('\n')
15167- );
15305+ );
15306+ }
15307+
15308+ const uniforms = (MMD_SA.THREEX.enabled) ? THREE.UniformsUtils.clone(THREE.ShaderLib.basic.uniforms) : {};
1516815309
15169- const uniforms = THREE.UniformsUtils.clone(THREE.ShaderLib.basic.uniforms);
1517015310 canvas_depth_transformed.width = canvas_depth_transformed.height = this.depth_dim;
1517115311 uniforms.Wallpaper3D_displacementMap = { value:new THREE.Texture(canvas_depth_transformed) };
1517215312 uniforms.Wallpaper3D_camera_factor = { get value() { return camera_factor; } };
@@ -15192,19 +15332,26 @@ return pos;
1519215332 }
1519315333 })();
1519415334
15195- material = new THREE.ShaderMaterial({
15196- vertexShader: vertexShader,
15197- fragmentShader: THREE.ShaderLib.basic.fragmentShader,
15198- uniforms: uniforms
15199- });
15200- material.color = new THREE.Color( 0xffffff );
15201- material.map = this.texture;
15202- material.fog = false;
15203- material.isMeshBasicMaterial = true;
15335+ if (!MMD_SA.THREEX.enabled) {
15336+ uniforms.Wallpaper3D_displacementMap.type = 't';
15337+ uniforms.Wallpaper3D_camera_factor.type = 'f';
15338+ uniforms.Wallpaper3D_camera_distance_offset.type = 'f';
15339+ uniforms.Wallpaper3D_scale_z.type = 'f';
15340+ uniforms.Wallpaper3D_pos_offset.type = 'v3';
15341+ }
15342+
15343+ if (MMD_SA.THREEX.enabled) {
15344+ material = new THREE.ShaderMaterial({
15345+ vertexShader: vertexShader,
15346+ fragmentShader: THREE.ShaderLib.basic.fragmentShader,
15347+ uniforms: uniforms
15348+ });
15349+ material.color = new THREE.Color( 0xffffff );
15350+ material.isMeshBasicMaterial = true;
1520415351
1520515352// https://stackoverflow.com/questions/77534730/the-fps-reduced-to-half-when-i-set-the-encoding-of-a-realtime-updated-texture-to
15206- material.onBeforeCompile = function ( shader ) {
15207- shader.fragmentShader = shader.fragmentShader.replace(
15353+ material.onBeforeCompile = function ( shader ) {
15354+ shader.fragmentShader = shader.fragmentShader.replace(
1520815355 '#include <map_fragment>',
1520915356 `
1521015357 #ifdef USE_MAP
@@ -15219,9 +15366,26 @@ return pos;
1521915366 #endif
1522015367
1522115368 `
15222- );
15223- };
15369+ );
15370+ };
15371+ }
15372+ else {
15373+ material = new THREE.MeshBasicMaterial({});
15374+ material.XRA_WALLPAPER_3D = true;
15375+ material._uniforms_append = uniforms;
15376+ /*
15377+ material = new THREE.ShaderMaterial({
15378+ vertexShader: THREE.ShaderLib.basic.vertexShader,
15379+ fragmentShader: THREE.ShaderLib.basic.fragmentShader,
15380+ uniforms: uniforms
15381+ });
15382+ */
15383+ console.log(material)
15384+ }
1522415385
15386+ material.color = new THREE.Color( 0xffffff );
15387+ material.map = this.texture;
15388+ material.fog = false;
1522515389}
1522615390
1522715391const mesh = new THREE.Mesh( geometry, material )
@@ -16242,7 +16406,13 @@ else {
1624216406}
1624316407
1624416408if (this.mesh.userData.use_depth_transform_shader) {
16245- this.mesh.material.uniforms.Wallpaper3D_displacementMap.value.needsUpdate = true;
16409+ if (this.mesh.material.uniforms?.Wallpaper3D_displacementMap) {
16410+ this.mesh.material.uniforms.Wallpaper3D_displacementMap.value.needsUpdate = true;
16411+ }
16412+ else {
16413+ // MMD mode doesn't have material.uniforms until program has compiled
16414+ System._browser.on_animation_update.add(()=>{ this.mesh.material.uniforms.Wallpaper3D_displacementMap.value.needsUpdate = true; }, 1,0);
16415+ }
1624616416 return;
1624716417}
1624816418
@@ -17372,7 +17542,7 @@ case "口角上げ":
1737217542 morph_alt.push(m, '∪', 'スマイル');
1737317543 break;
1737417544case "口角下げ":
17375- morph_alt.push(m, '∩', 'む');
17545+ morph_alt.push(m, '∩', 'む', 'ん', 'んあ' );
1737617546 break;
1737717547case "上":
1737817548case "下":
0 commit comments